Sitecore 9: Non Admin members are unable to publish items when Publishing.CheckSecurity is set to True - publish

Current Scenario(Sitecore 9) User is not able to publish any item to any publishing target, not even on the web database. We face this issue when we set Publishing.CheckSecurity to true in Sitecore.config.
There is no workflow on the item, User has all (Read, write, delete, create) access on the item.
I dug into Sitecore.Kernel Dll and found the difference
public bool CanPublish(ID itemId, User user, ref string explanation)
{
Assert.ArgumentNotNull(itemId, “itemId”);
Assert.ArgumentNotNull(user, “user”);
Assert.ArgumentNotNull(explanation, “explanation”);
if (!Settings.Publishing.CheckSecurity)
{
return true;
}
if (!this.CanPublishLanguage(itemId, user, ref explanation))
{
return false;
}
Item sourceItem = this.GetSourceItem(itemId);
if (sourceItem == null)
{
return this.CanPublishDeletion(itemId, user, ref explanation);
}
return this.CanPublishUpdate(sourceItem, user, ref explanation);
}
Earlier (Sitecore 8.1) “CanPublishLanguage” was not there. I have given all the access on language but still, my items are getting skipped while publishing. The function is returning false.
If I make this setting as false then it is working fine.
Please suggest if I am missing some more config change for this.

This issue is with Sitecore 9 and got fixed in Sitecore 9.0 Update 2.
Raised this issue with Sitecore and got the resolution for this.
The reported issue looks like one that has been fixed in the Sitecore 9.0 Update-2:
https://dev.sitecore.net/Downloads/Sitecore%20Experience%20Platform/90/Sitecore%20Experience%20Platform%2090%20Update2/Release%20Notes
When the Publishing.CheckSecurity setting is set to true, non-admin users are not able to publish content items even when they have all the appropriate security permissions 206940
To fix the issue we suggest you upgrade your Sitecore solution to the Sitecore XP 9.0 Update 2 (rev. 180604).
In case it is not possible, you can try the following patch: https://sitecore.box.com/s/swae96e2hhgrbid3keccmvzr4e8kbvr7
To install the patch follow the instructions from the readme file inside the archive.

Related

SetTag() on calendar event results in Action not allowed error for some users

I am facing the same issue as discussed here, however I checked all the needed permissions, and I can not reproduce this issue on my test system, and only some users have this issue on the production system.
I have one use case on production where this happens (but it happens on many users) with the following setup:
UserA has full permission to the calendar of UserB (manage and share)
UserA creates an event in the calendar of UserB
UserA uses then a calendar addon to set the tag -> which results in an error.
This is the code part where the tag is set:
const additionalInfo: AdditionalInfo = {
info: {
moreinfo: {
r: "somestring",
m: {
st: event.getStartTime().toJSON(),
et: event.getEndTime().toJSON(),
ro: ['ddd','ddsd'],
t: event.getTitle(),
h: generateHash(users.map(e => e.getEmail())),
c: event.getOriginalCalendarId()
}
}
},
}
event.setTag("Info", JSON.stringify(additionalInfo)) // Action not allowed
I also logged the tag and set the complete shared property on a test event without any problems. The length of the complete shared properties is around 600 characters so this should also not be a problem since I tested the max length which is apparently 1024.
I really have no clue what the issue is here....

Modify content records in Bolt CMS

I've added a 'product' content type to my Bolt installation. I want to track and update inventory when a purchase is made, so I added an integer field 'available'. I set up a test controller to modify the record. Everything appears to work, but the update never happens. What am I missing?
<?php
namespace Bundle\Site;
class CartController extends \Bolt\Controller\Base
{
public function addRoutes(\Silex\ControllerCollection $c)
{
$c->match('/test-save', [$this,'testSave']);
return $c;
}
public function testSave()
{
$result=false;
$repo = $this->app['storage']->getRepository('products');
$content = $repo->find(1);
//Error log output confirms that this is the correct record
error_log(get_class($this).'::'.__FUNCTION__.': '.json_encode($content));
$content->set('available',15);
$content->setDatechanged('now');
$result=$repo->save($content); //returns 1
return new \Symfony\Component\HttpFoundation\Response(json_encode($result), \Symfony\Component\HttpFoundation\Response::HTTP_OK);
}
}
It turns out that my code works. I was checking the result by reloading the back-end edit form, which had apparently cached its data, so I didn't see the value changing.
The same thing happens if I load the edit form in two browser tabs and update one, then refresh the other, so it looks like this is the best I can do.
I have faced a similar problem. Either the updated codes didn't show up or the result in the output is unchanged. Figured though this happened due to setting debug: false in the config.yml file. When debug is true your in bolt-data/app/ all cache files increases but this thing get sorted.
In production it is suggested that to keep debug: false but this problem checks-in too, hence the way you are dealing with it comes out to be the easiest way out without changing the configuration much.

How to fix Glass Mapper error - failed to find configuration for parent item type?

I have a Sitecore 8.1 CD instance. I also have some code that needs to create a content item in the Master database. (I am aware that is a no-no but I just need to figure this out at the moment) When my code attempts to use Glass Mapper to create a content item I get an error. Here is the code snippet and the error message. I am just trying to understand what the error means. I have a sense that this is simply a configuration problem. This code works fine on our Sitecore CM server. So I am hoping that by simply adjusting the config on our CD server I can get this to work. So far I have re-enabled the Master entry in ConnectionStrings.config and in Sitecore.config. But that hasn't fixed this.
SitecoreService service = new SitecoreService("master");
SimpleAes aes = new SimpleAes();
using (new SecurityDisabler())
{
Item parentItem = Factory.GetDatabase("master").GetItem("/sitecore/content/Non Page Content/Account Information/Shipping Addresses");
newAddress = service.Create(parentItem, newAddress); //THIS IS WHERE THE CODE FAILS
user.Addresses.Add(newAddress);
Utility.PublishItem(service.ResolveItem(newAddress));
id = aes.EncryptToString(newAddress.Id.ToString());
user.Addresses = user.Addresses;
user.Save();
}
Error Message:
Glass.Mapper.MapperException: Failed to find configuration for parent
item type Sitecore.Data.Items.Item ---> System.NullReferenceException:
Object reference not set to an instance of an object. at
System.Object.GetType() at
Glass.Mapper.Context.GetTypeConfiguration[T](Object obj, Boolean
doNotLoad, Boolean checkBase) at
Glass.Mapper.Sc.SitecoreService.Create[T,TK](TK parent, T newItem,
Boolean updateStatistics, Boolean silent) --- End of inner exception
stack trace --- at Glass.Mapper.Sc.SitecoreService.Create[T,TK](TK
parent, T newItem, Boolean updateStatistics, Boolean silent)
It is failing on this line
Item parentItem = Factory.GetDatabase("master").GetItem("/sitecore/content/Non Page Content/Account Information/Shipping Addresses");
if you put a check around it saying
if (parentItem != null) { // your code }
Then the code will work through and you will not get exception, but nothing will happen as well if parentItem is null.
Quick fix solution will be to give a 'master' DB connection string on your CD server (which is a no-no as you said). Better solution will be to expose master database through Sitecore Item API or your custom API, securing it through authentication and then calling this code from CD server via API.
I am not sure if you still are looking how to solve this issue, but when I faced today with it I found your question.
Problem is that your parentItem has type Item. It causes issue inside in Glass.
You can use any type as parent, but limitation is that it should not be inherited from Sitecore Item class.
Try this:
var parentItem = Factory.GetDatabase("master").GetItem("/sitecore/content/Non Page Content/Account Information/Shipping Addresses").GlassCast<BaseSitecoreItem>();
newAddress = service.Create(parentItem, newAddress);
where BaseSitecoreItem is some your Glass Model.
It helped me and hope will help you.

Redacted comments in MS's source code for .NET [duplicate]

The Reference Source page for stringbuilder.cs has this comment in the ToString method:
if (chunk.m_ChunkLength > 0)
{
// Copy these into local variables so that they
// are stable even in the presence of ----s (hackers might do this)
char[] sourceArray = chunk.m_ChunkChars;
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;
What does this mean? Is ----s something a malicious user might insert into a string to be formatted?
The source code for the published Reference Source is pushed through a filter that removes objectionable content from the source. Verboten words are one, Microsoft programmers use profanity in their comments. So are the names of devs, Microsoft wants to hide their identity. Such a word or name is substituted by dashes.
In this case you can tell what used to be there from the CoreCLR, the open-sourced version of the .NET Framework. It is a verboten word:
// Copy these into local variables so that they are stable even in the presence of race conditions
Which was hand-edited from the original that you looked at before being submitted to Github, Microsoft also doesn't want to accuse their customers of being hackers, it originally said races, thus turning into ----s :)
In the CoreCLR repository you have a fuller quote:
Copy these into local variables so that they are stable even in the presence of race conditions
Github
Basically: it's a threading consideration.
In addition to the great answer by #Jeroen, this is more than just a threading consideration. It's to prevent someone from intentionally creating a race condition and causing a buffer overflow in that manner. Later in the code, the length of that local variable is checked. If the code were to check the length of the accessible variable instead, it could have changed on a different thread between the time length was checked and wstrcpy was called:
// Check that we will not overrun our boundaries.
if ((uint)(chunkLength + chunkOffset) <= ret.Length && (uint)chunkLength <= (uint)sourceArray.Length)
{
///
/// imagine that another thread has changed the chunk.m_ChunkChars array here!
/// we're now in big trouble, our attempt to prevent a buffer overflow has been thawrted!
/// oh wait, we're ok, because we're using a local variable that the other thread can't access anyway.
fixed (char* sourcePtr = sourceArray)
string.wstrcpy(destinationPtr + chunkOffset, sourcePtr, chunkLength);
}
else
{
throw new ArgumentOutOfRangeException("chunkLength", Environment.GetResourceString("ArgumentOutOfRange_Index"));
}
}
chunk = chunk.m_ChunkPrevious;
} while (chunk != null);
Really interesting question though.
Don't think that this is the case - the code in question copies to local variables to prevent bad things happening if the string builder instance is mutated on another thread.
I think the ---- may relate to a four letter swear word...

DeviceInformation::FindAllAsync fails to find devices with RFCOMM service ID

I want a simple client/server setup with two Windows Phones, and I'm using the following code to set up the server:
auto providerTask = create_task(RfcommServiceProvider::CreateAsync(RfcommServiceId::FromUuid(GetServiceGUID())));
providerTask.then([this](RfcommServiceProvider^ p) -> task < void >
{
this->provider = p;
this->listener = ref new StreamSocketListener();
listener->ConnectionReceived += ref new Windows::Foundation::TypedEventHandler < Windows::Networking::Sockets::StreamSocketListener ^,
Windows::Networking::Sockets::StreamSocketListenerConnectionReceivedEventArgs ^ >
(this, &ConnectionManager::OnConnectionReceived);
return create_task(listener->BindServiceNameAsync(provider->ServiceId->AsString())).then([this]()
{
this->provider->StartAdvertising(listener);
});
}).then([](task<void> t)
{
//handle exceptions at the end of the chain
try
{
t.get();
}
catch (Platform::Exception^ ex)
{
if (ex->HResult == 0x9000000F)
{
OutputDebugString(L"Bluetooth is disabled.\n");
}
else throw ex;
}
});
GetServiceGUID() just returns the identifier I created for my App with VS's built-in GUID tool; the same one is also declared in the app manifest.
On the second device I'm looking for servers like this:
auto query = RfcommDeviceService::GetDeviceSelector(RfcommServiceId::FromUuid(GetServiceGUID()));
create_task(DeviceInformation::FindAllAsync(query))
.then([this](DeviceInformationCollection^ services)
{
if (services->Size > 0)
{
OutputDebugString(L"We've found a server!\n");
OutputDebugString(services->First()->Current->Name->Data());
}
});
The call to FindAllAsync always returns an empty collection, even though both devices are shown as paired in the settings. However, if I use RfcommServiceId::ObexObjectPush instead of FromUuid when setting up the server and later when enumerating devices, it works fine. Does anyone know why this is happening?
What do the AQS selector strings look like in both cases?
The problem is either:
The selector doesn't match the interface on the system unexpectedly
Basically the filter is used to match properties on the devices interfaces currently in KM PnP state. If an interface's properties match what is logically being requested in the selector, then it is added to the device information collection.
Maybe try FindAllAsync without a selector, then see what interfaces are currently being enumerated by KM PnP. Request the properties that are in the selector. Once you see the interface that you think you should be seeing, logically figure out why it is not matching with the selector.
The device is not paired.
If the device is not paired, then there won't be any devnodes or interfaces to represent it. Hence it cannot be discovered by FindAllAsync
The device is paired, but does not have the profile you think it has.
The Bluetooth bus driver will only create PnP state for profiles it understands. The PnP state is required for FindAllAsync to find it. RFCOMM is a basic one, so it should work though.
Anyway, start with writing some test code as outlined in 1. That will give you some infortmation to get further in your investigation.
Also, checkout the new Windows 10 API changes for Windows.Devices.Enumeration. There are new ways to discover Bluetooth devices.
-Sam