The best way to pass records to a class

This is the best method to pass the selected records from a Form to a Class

static void Main(Args args)
{
    MultiSelectionHelper    multiSelectionHelper;
    AssetTable              AssetTable;
    ;

    multiSelectionHelper = MultiSelectionHelper::createFromCaller(args.caller());
    assetTable  = multiSelectionHelper.getFirst();
    while (assetTable)
    {
        info(assetTable.AssetId);
        assetTable = multiSelectionHelper.getNext();
    }
}

MultiSelectionHelper class helps to iterate into selected records.
If you are using args object on your target class consider to use the method:

multiSelectionHelper.parmCacheRecords(true);

How to get SalesLine record from ReqTrans table using X++ AX 2012

Add these two methods to the ReqTrans table

public SalesLine getSalesLine(ReqTrans _reqTrans)
{
    ReqTrans        reqTrans_Settle,reqTrans_next;
    SalesLine       salesLine;
    ;
    reqTrans_Settle = _reqTrans.getSettleTrans();
    do
    {
        select reqTrans_next
            where reqTrans_next.RefId == reqTrans_Settle.RefId
               && reqTrans_next.Direction == InventDirection::Receipt;
        if (!reqTrans_next)
        {
            break;
        }
        reqTrans_Settle = reqTrans_next.getSettleTrans();
    }
    while(reqTrans_next);
 
    if(reqTrans_Settle.RefType == ReqRefType::Sales)
    {
        salesLine = SalesLine::findInventTransId(InventTransOrigin::find(reqTrans_Settle.InventTransOrigin).InventTransId);
    }
 
    return salesLine;
}
 
private ReqTrans getSettleTrans()
{
    ReqTrans    reqTrans_Settle;
    ReqTransCov reqTransCov;
    ;
 
    switch(this.Direction)
    {
        case InventDirection::Issue:
                select reqTransCov
                    where reqTransCov.IssueRecId == this.RecId;
 
                reqTrans_Settle = reqTrans::findRecId(reqTransCov.ReceiptRecId);
            break;
 
        case InventDirection::Receipt:
                select reqTransCov
                    where reqTransCov.ReceiptRecId == this.RecId;
 
                reqTrans_Settle = reqTrans::findRecId(reqTransCov.IssueRecId);
            break;
 
    }
 
    return reqTrans_Settle;
}

Asp .NET Core custom Identity PasswordHasher

A few days ago I started to develop a new web application using ASP.NET Core, that work with the same database (so the same Users credentials) of a web application made in ASP .NET MVC 5. That’s fine and funny. But the big problem is: Identity on ASP.NET Core changed the password’s hash and if you login with the new version it will update the old hash with the new one, so on the other application is no longer possible login.
What can we do to tell to Identity: don’t change the existing password hash?
A solution is take from git hub the original class PasswordHasher and make my version, on override the method HashPassword return always the password hash of V2, so is guarantee the compatibility with previous versions of Identity

/// 
<summary>
/// Returns a hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.
/// </summary>

/// <param name="user">The user whose password is to be hashed.</param>
/// <param name="password">The password to hash.</param>
/// <returns>A hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.</returns>
public override string HashPassword(TUser user, string password)
{
    if (password == null)
    {
        throw new ArgumentNullException(nameof(password));
    }

    //if (_compatibilityMode == PasswordHasherCompatibilityMode.IdentityV2)
    //{
    //	return Convert.ToBase64String(HashPasswordV2(password, _rng));
    //}
    //else
    //{
    //	return Convert.ToBase64String(HashPasswordV3(password, _rng));
    //}
                //retunr always the hash of V2
    return Convert.ToBase64String(HashPasswordV2(password, _rng));
}

So my class look like this:

using System;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Identity;

namespace MyApp.Manager.Services
{
	/// 
<summary>
	/// Implements the standard Identity password hashing.
	/// </summary>

	/// <typeparam name="TUser">The type used to represent a user.</typeparam>
	public class MyPasswordHasher<TUser> : PasswordHasher<TUser> where TUser : class
	{
		/* =======================
         * HASHED PASSWORD FORMATS
         * =======================
         * 
         * Version 2:
         * PBKDF2 with HMAC-SHA1, 128-bit salt, 256-bit subkey, 1000 iterations.
         * (See also: SDL crypto guidelines v5.1, Part III)
         * Format: { 0x00, salt, subkey }
         *
         * Version 3:
         * PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations.
         * Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
         * (All UInt32s are stored big-endian.)
         */

		private readonly PasswordHasherCompatibilityMode _compatibilityMode;
		private readonly int _iterCount;
		private readonly RandomNumberGenerator _rng;

		/// 
<summary>
		/// Creates a new instance of <see cref="PasswordHasher{TUser}"/>.
		/// </summary>

		/// <param name="optionsAccessor">The options for this instance.</param>
		public StarmePasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null)
		{
			var options = optionsAccessor?.Value ?? new PasswordHasherOptions();

			_compatibilityMode = PasswordHasherCompatibilityMode.IdentityV2;
			switch (_compatibilityMode)
			{
				case PasswordHasherCompatibilityMode.IdentityV2:
					// nothing else to do
					break;

				case PasswordHasherCompatibilityMode.IdentityV3:
					_iterCount = options.IterationCount;
					if (_iterCount < 1)
					{
						throw new InvalidOperationException("");
					}
					break;

				default:
					throw new InvalidOperationException("");
			}
			_rng = RandomNumberGenerator.Create();
			//_rng = options.Rng;
		}

		// Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized.
		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private static bool ByteArraysEqual(byte[] a, byte[] b)
		{
			if (a == null && b == null)
			{
				return true;
			}
			if (a == null || b == null || a.Length != b.Length)
			{
				return false;
			}
			var areSame = true;
			for (var i = 0; i < a.Length; i++)
			{
				areSame &= (a[i] == b[i]);
			}
			return areSame;
		}

		/// 
<summary>
		/// Returns a hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.
		/// </summary>

		/// <param name="user">The user whose password is to be hashed.</param>
		/// <param name="password">The password to hash.</param>
		/// <returns>A hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.</returns>
		public override string HashPassword(TUser user, string password)
		{
			if (password == null)
			{
				throw new ArgumentNullException(nameof(password));
			}

			//if (_compatibilityMode == PasswordHasherCompatibilityMode.IdentityV2)
			//{
			//	return Convert.ToBase64String(HashPasswordV2(password, _rng));
			//}
			//else
			//{
			//	return Convert.ToBase64String(HashPasswordV3(password, _rng));
			//}
            //retunr always the hash of V2
			return Convert.ToBase64String(HashPasswordV2(password, _rng));
		}

		private static byte[] HashPasswordV2(string password, RandomNumberGenerator rng)
		{
			const KeyDerivationPrf Pbkdf2Prf = KeyDerivationPrf.HMACSHA1; // default for Rfc2898DeriveBytes
			const int Pbkdf2IterCount = 1000; // default for Rfc2898DeriveBytes
			const int Pbkdf2SubkeyLength = 256 / 8; // 256 bits
			const int SaltSize = 128 / 8; // 128 bits

			// Produce a version 2 (see comment above) text hash.
			byte[] salt = new byte[SaltSize];
			rng.GetBytes(salt);
			byte[] subkey = KeyDerivation.Pbkdf2(password, salt, Pbkdf2Prf, Pbkdf2IterCount, Pbkdf2SubkeyLength);

			var outputBytes = new byte[1 + SaltSize + Pbkdf2SubkeyLength];
			outputBytes[0] = 0x00; // format marker
			Buffer.BlockCopy(salt, 0, outputBytes, 1, SaltSize);
			Buffer.BlockCopy(subkey, 0, outputBytes, 1 + SaltSize, Pbkdf2SubkeyLength);
			return outputBytes;
		}

		private byte[] HashPasswordV3(string password, RandomNumberGenerator rng)
		{
			return HashPasswordV3(password, rng,
				prf: KeyDerivationPrf.HMACSHA256,
				iterCount: _iterCount,
				saltSize: 128 / 8,
				numBytesRequested: 256 / 8);
		}

		private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested)
		{
			// Produce a version 3 (see comment above) text hash.
			byte[] salt = new byte[saltSize];
			rng.GetBytes(salt);
			byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);

			var outputBytes = new byte[13 + salt.Length + subkey.Length];
			outputBytes[0] = 0x01; // format marker
			WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
			WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
			WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
			Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
			Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
			return outputBytes;
		}

		private static uint ReadNetworkByteOrder(byte[] buffer, int offset)
		{
			return ((uint)(buffer[offset + 0]) << 24)
				| ((uint)(buffer[offset + 1]) << 16)
				| ((uint)(buffer[offset + 2]) << 8)
				| ((uint)(buffer[offset + 3]));
		}

		/// 
<summary>
		/// Returns a <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.
		/// </summary>

		/// <param name="user">The user whose password should be verified.</param>
		/// <param name="hashedPassword">The hash value for a user's stored password.</param>
		/// <param name="providedPassword">The password supplied for comparison.</param>
		/// <returns>A <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.</returns>
		/// <remarks>Implementations of this method should be time consistent.</remarks>
		public override PasswordVerificationResult VerifyHashedPassword(TUser user, string hashedPassword, string providedPassword)
		{
			if (hashedPassword == null)
			{
				throw new ArgumentNullException(nameof(hashedPassword));
			}
			if (providedPassword == null)
			{
				throw new ArgumentNullException(nameof(providedPassword));
			}

			byte[] decodedHashedPassword = Convert.FromBase64String(hashedPassword);

			// read the format marker from the hashed password
			if (decodedHashedPassword.Length == 0)
			{
				return PasswordVerificationResult.Failed;
			}
			switch (decodedHashedPassword[0])
			{
				case 0x00:
					if (VerifyHashedPasswordV2(decodedHashedPassword, providedPassword))
					{
						// This is an old password hash format - the caller needs to rehash if we're not running in an older compat mode.
						return (_compatibilityMode == PasswordHasherCompatibilityMode.IdentityV3)
							? PasswordVerificationResult.SuccessRehashNeeded
							: PasswordVerificationResult.Success;
					}
					else
					{
						return PasswordVerificationResult.Failed;
					}

				case 0x01:
					int embeddedIterCount;
					if (VerifyHashedPasswordV3(decodedHashedPassword, providedPassword, out embeddedIterCount))
					{
						// If this hasher was configured with a higher iteration count, change the entry now.
						return (embeddedIterCount < _iterCount) ? PasswordVerificationResult.SuccessRehashNeeded : PasswordVerificationResult.Success; } else { return PasswordVerificationResult.Failed; } default: return PasswordVerificationResult.Failed; // unknown format marker } } private static bool VerifyHashedPasswordV2(byte[] hashedPassword, string password) { const KeyDerivationPrf Pbkdf2Prf = KeyDerivationPrf.HMACSHA1; // default for Rfc2898DeriveBytes const int Pbkdf2IterCount = 1000; // default for Rfc2898DeriveBytes const int Pbkdf2SubkeyLength = 256 / 8; // 256 bits const int SaltSize = 128 / 8; // 128 bits // We know ahead of time the exact length of a valid hashed password payload. if (hashedPassword.Length != 1 + SaltSize + Pbkdf2SubkeyLength) { return false; // bad size } byte[] salt = new byte[SaltSize]; Buffer.BlockCopy(hashedPassword, 1, salt, 0, salt.Length); byte[] expectedSubkey = new byte[Pbkdf2SubkeyLength]; Buffer.BlockCopy(hashedPassword, 1 + salt.Length, expectedSubkey, 0, expectedSubkey.Length); // Hash the incoming password and verify it byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, Pbkdf2Prf, Pbkdf2IterCount, Pbkdf2SubkeyLength); return ByteArraysEqual(actualSubkey, expectedSubkey); } private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string password, out int iterCount) { iterCount = default(int); try { // Read header information KeyDerivationPrf prf = (KeyDerivationPrf)ReadNetworkByteOrder(hashedPassword, 1); iterCount = (int)ReadNetworkByteOrder(hashedPassword, 5); int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9); // Read the salt: must be >= 128 bits
				if (saltLength < 128 / 8) { return false; } byte[] salt = new byte[saltLength]; Buffer.BlockCopy(hashedPassword, 13, salt, 0, salt.Length); // Read the subkey (the rest of the payload): must be >= 128 bits
				int subkeyLength = hashedPassword.Length - 13 - salt.Length;
				if (subkeyLength < 128 / 8) { return false; } byte[] expectedSubkey = new byte[subkeyLength]; Buffer.BlockCopy(hashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length); // Hash the incoming password and verify it byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength); return ByteArraysEqual(actualSubkey, expectedSubkey); } catch { // This should never occur except in the case of a malformed payload, where // we might go off the end of the array. Regardless, a malformed payload // implies verification failed. return false; } } private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value) { buffer[offset + 0] = (byte)(value >> 24);
			buffer[offset + 1] = (byte)(value >> 16);
			buffer[offset + 2] = (byte)(value >> 8);
			buffer[offset + 3] = (byte)(value >> 0);
		}
	}
}

And then add this code to Startup.cs

services.AddScoped<IPasswordHasher<ApplicationUser>, MyPasswordHasher<ApplicationUser>>();

How to set value using jQuery on custom Editor Template of a Kendo Grid

If you neeed to update a field on a Custom Editor template of a Kendo grid using jQuery the only method I found that works is this:

 
var myvar = $("#myid");
myvar.val("newValue");
myvar.trigger("change", { value: myvar.val() });

 

[AX 2012 R3] How to get avail quantity of a product by ItemId and get details by inventory dimensions (InventDimId)

 InventDimOnHand onHand;
 InventDimOnHandIterator iter;
 InventDimOnHandMember member;
 InventOnhand inventOnhand;
 ItemId itemId;
 InventDim inventDimCrit;
 InventDimParm inventDimParmCrit, inventDimParmOnHandLevel;
 InventDim inventDim;
 InventDimOnHandLevel level;
 ;

 itemId = '123456';

 // Known dimensions
 inventDimCrit.wMSLocationId = 'location01';
 inventDimCrit = InventDim::findOrCreate(inventDimCrit);

 // Determine which of the known dimensions to use
 inventDimParmCrit.WMSLocationIdFlag = true;

 level = InventDimOnHandLevel::DimParm;

 // Determines the level of detail returned
 inventDimParmOnHandLevel.ItemIdFlag = true;
 inventDimParmOnHandLevel.InventLocationIdFlag = true;
 inventDimParmOnHandLevel.WMSLocationIdFlag = true;
 inventDimParmOnHandLevel.InventBatchIdFlag = true;

 onHand = InventDimOnHand::newPhysicalArrived(itemId, inventDimCrit, InventDimParmCrit, level, inventDimParmOnHandLevel);

 iter = onHand.onHandIterator();
 while (iter.more())
 {
 member = iter.value();
 inventDim = InventDim::find(member.parmInventDimId());
 inventDimParmOnHand.initFromInventDim(inventDim);
 inventOnHand = InventOnhand::newParameters(itemId, inventDim,inventDimParmOnHand);
 info(con2str([member.parmItemId(), inventDim.inventLocationId, inventDim.inventBatchId, inventDim.LicensePlateId, inventDim.inventSerialId, member.parmInventQty(), inventOnHand.availPhysical()]));

 iter.next();
 }

 info('Done'); 

[AX 2012 R3] How to get product color description

We want to display the description of a dimension (in this case the colour) of a product

We just need the ItemId and InventColorId

productAx

static void GetColorDescription(Args _args)
{
 ItemId ItemId = "123456789"; //Change with your ItemId
 EcoResProductMasterColor EcoResProductMasterColor;
 EcoResProductMasterDimensionValue EcoResProductMasterDimensionValue;
 EcoResColor EcoResColor;
 EcoResProductMaster EcoResProductMaster;
 EcoResProductMasterDimValueTranslation EcoResProductMasterDimValueTranslation;
 
 EcoResColorName EcoResColorName = InventDim::find("InventDimId").InventColorId; 

 select * from EcoResProductMasterDimValueTranslation
 join RecId from EcoResProductMasterDimensionValue
 where EcoResProductMasterDimValueTranslation.ProductMasterDimensionValue
 == EcoResProductMasterDimensionValue.RecId
 join RecId from EcoResProductMasterColor
 where EcoResProductMasterDimensionValue.RecId == EcoResProductMasterColor.RecId
 join RecId from EcoResColor
 where EcoResColor.RecId == EcoResProductMasterColor.Color
 && EcoResColor.Name == EcoResColorName
 join RecId from EcoResProductMaster
 where EcoResProductMasterColor.ColorProductMaster == EcoResProductMaster.RecId
 && EcoResProductMaster.DisplayProductNumber == ItemId;

 info(EcoResProductMasterDimValueTranslation.Name);
}

In case you don’t have any translaction
ax2012r3_product_with_no_translation
the object EcoResProductMasterDimValueTranslation.Name will be empty, so you can retrive the Deault value using this code:

static void GetColorDescription(Args _args)
{
 ItemId ItemId = "123456789"; //Change with your ItemId
 EcoResProductMasterColor EcoResProductMasterColor;
 EcoResProductMasterDimensionValue EcoResProductMasterDimensionValue;
 EcoResColor EcoResColor;
 EcoResProductMaster EcoResProductMaster;
 EcoResProductMasterDimValueTranslation EcoResProductMasterDimValueTranslation;
 
 EcoResColorName EcoResColorName = InventDim::find("InventDimId").InventColorId; 

 select * from EcoResProductMasterDimValueTranslation
 join RecId from EcoResProductMasterDimensionValue
 where EcoResProductMasterDimValueTranslation.ProductMasterDimensionValue
 == EcoResProductMasterDimensionValue.RecId
 join RecId from EcoResProductMasterColor
 where EcoResProductMasterDimensionValue.RecId == EcoResProductMasterColor.RecId
 join RecId from EcoResColor
 where EcoResColor.RecId == EcoResProductMasterColor.Color
 && EcoResColor.Name == EcoResColorName
 join RecId from EcoResProductMaster
 where EcoResProductMasterColor.ColorProductMaster == EcoResProductMaster.RecId
 && EcoResProductMaster.DisplayProductNumber == ItemId;

if(EcoResProductMasterDimValueTranslation.Name)
{
info(EcoResProductMasterDimValueTranslation.Name);
}
else
{
EcoResProductMasterDimValueTranslation = EcoResProductMasterDimValueTranslation::getNameOrDefaultName(EcoResProductMasterDimensionValueId, SystemParameters::getSystemLanguageId()); info(EcoResProductMasterDimValueTranslation.Name);
info(EcoResProductMasterDimValueTranslation.Name);
}

XE One Day – Real App

Riporto di seguito un evento organizzato dalla community XEDotNet

Festeggia i 10 anni con noi, con un’evento da non perdere.
Una giornata di sessioni per far vedere come realizzare un intero progetto composto da varie applicazioni collegate tra loro.
Dal database, ad un’applicazione web per l’esposizione delle API ed il data-entry, e continuando con l’uso di queste API da dispositivi mobile e da device.

Sessioni:

  • 09.00 – 09.30 – Intro
  • 09.30 – 10.40 – Il database, questo indispensabile sconosciuto
  • 11.00 – 12.10 – Umbraco, dal backend per la tua app, alle API pubbliche
  • 12.10 – 14.00 – Pranzo
  • 14.00 – 15.10 – Angular e Typescript un binomio perfetto
  • 15.20 – 16.30 – 1 hour app with Xamarin.Forms
  • 16.50 – 18.00 – Windows 10 IoT Core, un esempio reale
  • 20.00 – 23.00 – Community Pizza – 10 anni

Maggiori Informazioni ed iscrizione

How To Create a Delegate in TypeScript

This is a snippet that can allow you to create a Delegate for the function GridDataBound

function createDelegate(instance: any, method: any): any {
    return function () {
        return method.apply(instance, arguments);
    }
}

class ClassName {
    public DataBound$dlg: any;

    constructor() {
        this.GridDataBound$dlg = createDelegate(this, this.GridDataBound);
    }

GridDataBound(e: any): void {
        return;
    }
}

How to install CUPS on Raspberry PI and configure Brother DCP-7030

cups

 

First of all we need to install CUPS, so connect to Raspberry on SSH and give this commands:

sudo apt-get update
sudo apt-get install cups

 

Configure CUPS
Open with su permissions the file: /etc/cups/cupsd.conf
Now the content of file must look like this:

#
# "$Id: cupsd.conf.in 9407 2010-12-09 21:24:51Z mike $"
#
# Sample configuration file for the CUPS scheduler. See "man cupsd.conf" for a
# complete description of this file.
## Log general information in error_log - change "warn" to "debug"
# for troubleshooting...
LogLevel warn

# Deactivate CUPS' internal logrotating, as we provide a better one, especially
# LogLevel debug2 gets usable now
MaxLogSize 0

# Only listen for connections from the local machine.
Listen 631
Listen /var/run/cups/cups.sock

# Show shared printers on the local network.
Browsing On
BrowseOrder allow,deny
BrowseAllow all
BrowseLocalProtocols CUPS dnssd

# Default authentication type, when authentication is required...
DefaultAuthType Basic

# Web interface setting...
WebInterface Yes

# Restrict access to the server...
<Location />
Order allow,deny
Allow 192.168.1.*
</Location>

# Restrict access to the admin pages...
<Location /admin>
Order allow,deny
Allow 192.168.1.*
</Location>

# Restrict access to configuration files...
<Location /admin/conf>
AuthType Default
Require user @SYSTEM
Order allow,deny
Allow 192.168.1.*
</Location>

# Set the default printer/job policies...
<Policy default>
# Job/subscription privacy...
JobPrivateAccess default
JobPrivateValues default
SubscriptionPrivateAccess default
SubscriptionPrivateValues default

# Job-related operations must be done by the owner or an administrator...
<Limit Create-Job Print-Job Print-URI Validate-Job>
Order deny,allow
</Limit>

<Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
Require user @OWNER @SYSTEM
Order deny,allow
</Limit>

# All administration operations require an administrator to authenticate...
<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default CUPS-Get-Devices>
AuthType Default
Require user @SYSTEM
Order deny,allow
</Limit>

# All printer operations require a printer operator to authenticate...
<Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
AuthType Default
Require user @SYSTEM
Order deny,allow
</Limit>

# Only the owner or an administrator can cancel or authenticate a job...
<Limit Cancel-Job CUPS-Authenticate-Job>
Require user @OWNER @SYSTEM
Order deny,allow
</Limit>

<Limit All>
Order deny,allow
</Limit>
</Policy>

# Set the authenticated printer/job policies...
<Policy authenticated>
# Job/subscription privacy...
JobPrivateAccess default
JobPrivateValues default
SubscriptionPrivateAccess default
SubscriptionPrivateValues default

# Job-related operations must be done by the owner or an administrator...
<Limit Create-Job Print-Job Print-URI Validate-Job>
AuthType Default
Order deny,allow
</Limit>

<Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document>
AuthType Default
Require user @OWNER @SYSTEM
Order deny,allow
</Limit>

# All administration operations require an administrator to authenticate...
<Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default>
AuthType Default
Require user @SYSTEM
Order deny,allow
</Limit>

# All printer operations require a printer operator to authenticate...
<Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs>
AuthType Default
Require user @SYSTEM
Order deny,allow
</Limit>

# Only the owner or an administrator can cancel or authenticate a job...
<Limit Cancel-Job CUPS-Authenticate-Job>
AuthType Default
Require user @OWNER @SYSTEM
Order deny,allow
</Limit>

<Limit All>
Order deny,allow
</Limit>
</Policy>

#
# End of "$Id: cupsd.conf.in 9407 2010-12-09 21:24:51Z mike $".
#

Now restart the daemon in order to apply the new configuration

sudo service cups restart

Now we must add to usergroup lpadmin our user

sudo usermod -aG lpadmin pi

Configure the printer
Navigate to the Administration page of cups: http:///<Your_PI_IP_ADDRESS>:631/admin

and click on “Add Printer” button

 

add_printer

Now under Local Printers select the Brother DCP-7030 Printer and click “Continue”

On next page select a Name ore leave it as proposed and check the checkbox “Share This Printer”

share_printer

Click “Continue” button

On this page choose the driver Brother DCP-1200 Foomatic/hl1250 (recommended) (en)

driver_printer

Click “Add Printer” and we have done the server configuration!

 

Now to configure Windows clients to use this printer we must:

  1. Download the driver for windows: http://support.brother.com/g/b/downloadtop.aspx?c=gb&lang=en&prod=dcp7030_all
  2. Add a New Printer and enter this address: http://<Ip_Address_PI>:631/printers/<PrinterName>

client_printer

 

 

 

 

 

 

 

How to solve Exception : The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value with Entity Framework when calling SaveChanges

In order to fix this Issue you need to go on your EDMX file and View the Model.
So select the field interested and under it’s properties select “Computed” for the property StoreGeneratedPattern