Retrieving Specific Active Directory Record Attributes using C# - active-directory

I've been asked to set up a process which monitors the active directory, specifically certain accounts, to check that they are not locked so that should this happen, the support team can get an early warning.
I've found some code to get me started which basically sets up requests and adds them to a notification queue. This event is then assigned to a change event and has an ObjectChangedEventArgs object passed to it.
Currently, it iterates through the attributes and writes them to a text file, as so:
private static void NotifierObjectChanged(object sender,
ObjectChangedEventArgs e)
{
if (e.ResultEntry.Attributes.AttributeNames == null)
{
return;
}
// write the data for the user to a text file...
using (var file = new StreamWriter(#"C:\Temp\UserDataLog.txt", true))
{
file.WriteLine("{0} {1}", DateTime.UtcNow.ToShortDateString(), DateTime.UtcNow.ToShortTimeString());
foreach (string attrib in e.ResultEntry.Attributes.AttributeNames)
{
foreach (object item in e.ResultEntry.Attributes[attrib].GetValues(typeof(string)))
{
file.WriteLine("{0}: {1}", attrib, item);
}
}
}
}
What I'd like is to check the object and if a specific field, such as name, is a specific value, then check to see if the IsAccountLocked attribute is True, otherwise skip the record and wait until the next notification comes in. I'm struggling how to access specific attributes of the ResultEntry without having to iterate through them all.
I hope this makes sense - please ask if I can provide any additional information.
Thanks
Martin

This could get gnarly depending upon your exact business requirements. If you want to talk in more detail ping me offline and I'm happy to help over email/phone/IM.
So the first thing I'd note is that depending upon what the query looks like before this, this could be quite expensive or error prone (ie missing results). This worries me somewhat as most sample code out there gets this wrong. :) How are you getting things that have changed? While this sounds simple, this is actually a somewhat tricky question in directory land, given the semantics supported by AD and the fact that it is a multi-master system where writes happen all over the place (and replicate in after the fact).
Other variables would be things like how often you're going to run this, how large the data set could be in AD, and so on.
AD has some APIs built to help you here (the big one that comes to mind is called DirSync) but this can be somewhat complicated if you haven't used it before. This is where the "ping me offline" part comes in.
To your exact question, I'm assuming your result is actually a SearchResultEntry (if not I can revise, tell me what you have in hand). If that is the case then you'll find an Attributes field hanging off of that guy, and from there there is AttributeNames and Values. I think you'll see how it works from there if you have Values in hand, for example:
foreach (var attr in sre.Attributes.Values)
{
var da = (DirectoryAttribute)attr;
Console.WriteLine(da.Name);
foreach (var val in da.GetValues(typeof(byte[])))
{
// Handle a byte[] val ...
}
}
As I said, if you have something other than a SearchResultEntry in hand, let us know and I can revise the code sample.

Related

Is FLIP-140 still correct in how it describes sorting/spilling data?

FLIP-140 states:
We will introduce a sorting step (with potential spilling, reusing the UnilateralSortMerger implementation) before every keyed operator for sorting/grouping inputs by their keys. This will allow us to process records in per-key groups, which will enable us to use a simplified implementation of a StateBackend that is not organized in key groups and only ever keeps values for a single key.
The single key at a time execution will be used for the Batch style execution as decided by the algorithm described in FLIP-134: DataStream Semantics for Bounded Input .
Moreover it will be possible to disable it through a execution.sorted-shuffles.enabled configuration option.
However I see not documentation for execution.sorted-shuffles.enabled, and no references to it in the code. So is the above description of how things work still correct? Wondering how the "only keep one key's state around" would work without sorting.
This code makes me think that both the sorting and special state backend are being used with batch execution:
private void setBatchStateBackendAndTimerService(StreamGraph graph) {
boolean useStateBackend = configuration.get(ExecutionOptions.USE_BATCH_STATE_BACKEND);
boolean sortInputs = configuration.get(ExecutionOptions.SORT_INPUTS);
checkState(
!useStateBackend || sortInputs,
"Batch state backend requires the sorted inputs to be enabled!");
if (useStateBackend) {
LOG.debug("Using BATCH execution state backend and timer service.");
graph.setStateBackend(new BatchExecutionStateBackend());
graph.setChangelogStateBackendEnabled(TernaryBoolean.FALSE);
graph.setCheckpointStorage(new BatchExecutionCheckpointStorage());
graph.setTimerServiceProvider(
BatchExecutionInternalTimeServiceManager::create);
} else {
graph.setStateBackend(stateBackend);
graph.setChangelogStateBackendEnabled(changelogStateBackendEnabled);
}
}

CakePHP 3.4: how to cache virtual fields

Is there a way to cache virtual fields? I mean automatically, with the entity to which they belong, because I understand that, even if an entity is retrieved from the cache, virtual fields are generated whenever it is necessary.
Obviously I know I can take care of it personally, so (example):
protected function _getFullName()
{
$fullName = Cache::read('full_name_for_' . $this->_properties['id'], 'users');
if (empty($fullName)) {
$fullName = $this->_properties['first_name'] . ' ' . $this->_properties['last_name'];
Cache::write('full_name_for_' . $this->_properties['id'], $fullName, 'users');
}
return $fullName;
}
But I wanted to know if in fact CakePHP can do it directly.
EDIT
Context.
The Post entity has the text property. text can contain images (as html code), even remote. Now I have to store somewhere the url of the first image contained in the text and its size. So I have created the first_image virtual field, that uses a regex. The problem is rather with the image size: I can not do run every time the getimagesize() function, especially if the image is remote, for reasons that you can easily understand. So how to do?
Is there a way to cache virtual fields?
No.
And what you do doesn't make much sense. The caching is for sure causing more overhead than that you gain anything from it in this case.
Use concat() on the DB level to concatenate the name instead.
Also if there would be a real need to cache a virtual property, then I would say there went something clearly wrong in the architecture.
It makes sense to me to want to prevent code in accessors/virtual fields from being executed more than once on the same request, which can easily happen if you use them several places in your script.
You can do a solution like this, but I'm not entirely sure how kosher it is:
private $fullName_cache = false;
protected function _getFullName()
{
if(!$this->fullName_cache){
$fullName = Cache::read('full_name_for_' . $this->_properties['id'], 'users');
if (empty($fullName)) {
$fullName = $this->_properties['first_name'] . ' ' . $this->_properties['last_name'];
Cache::write('full_name_for_' . $this->_properties['id'], $fullName, 'users');
}
$this->fullName_cache = $fullName;
}
return $this->fullName_cache;
}
I think there might be a nicer way to do this. There is mention of this sort of thing in the cookbook:
Code in your accessors is executed each time you reference the field. You can use a local variable to cache it if you are performing a resource-intensive operation in your accessor like this: $myEntityProp = $entity->my_property.
Anyone had luck implementing this?

Grails/GORM domain saving - transient object workaround

I found a work around to a problem I had, and I want to know if it is valid or not. It is a similar problem to: Grails Gorm : Object references an unsaved transient instance
Lets assume I have two domain Objects (names changed to protect the guilty).
public class Shelf {
String name
Set<Book> books = [] as Set
static hasMany = [books: Book]
}
and
public class Book {
String title
Shelf shelf
}
So this means that 1 Shelf contains 0 to many Books, and one Book can be on only one Shelf.
This Shelf is very large. And at some point, it contains 80,000 Books. All stored nicely in the DB. Of course, adding new Books is getting slower and slower.
This is done by:
Book book1 = new Book("Awesome Title")
existingShelf.addToBooks(book1)
existingShelf.save(flush: true) // super slow
This is slow. Mainly (I assume) because GORM has to confirm the other 80,000 records.
So I did this to try to work around the slow point.
Book book2 = new Book("Awesome Title 2")
book2.save(flush: true)
This gives me an "Object references an unsaved transient instance", which I guess makes sense - the "shelf" value is empty.
So I did something a little weird:
Book book3 = new Book("Awesome Title 3")
book3.shelf = new Shelf()
book3.shelf.id = <known/valid id here>
book2.save(flush: true)
This works. It saves. There are no referential errors. Further code that depends on this... works.
I just made a call that last minutes and reduced it down to seconds.
But that seems too easy. I'm sure I worked around Grails magic some how. And probably broke something in the process.
Advice? Explanations?
Yes, using addTo* methods can be slow. If you look at the generated SQL you'll understand why. Doing the following:
new Book(title: "GORM Performance", shelf: grailsShelf).save()
will be faster and there is technically nothing wrong with it. Just be aware of that your instance of grailsShelf.books will not contain the new book until you've refreshed the collection from the database. This is part of what the addTo* method does for you.
Side note:
Set<Book> books = [] as Set
is unnecessary.

Document status that depend on the user type object

I have the following objects: L1User, L2User, L3User (all inherits from User) and Document.
Every user can create the document but depending on the user type, the document will have a different status. So in case it's L1User, the document will be created with L1 status and so on:
Solution 1
Please note that after document is created, it will be saved in the database, so it should be natural to have a method create_document(User user) in Document object. In the method body I could check which type is the user and set manually appropriate status. Such approach seems rather not OOP to me.
Solution 2
Ok, so the next approach would be to have all users implement a common method (say create_document(Document doc)) which will set a status associated with the user and save the document in the database. My doubt here is that the document should be saved in it's own class, not the user.
Solution 3
So the final approach would similar to the above, except that the user will return modified document object to it's create_document(User user) method and save will be performed there. The definition of the method would be like this:
create_document(User user)
{
this = user.create_document(this);
this->save();
}
It also doesn't seems right to me...
Can anyone suggest a better approach?
I think that both Solutions 2 and 3 are ok from the OO point of view, since you are properly delegating the status assignment to the user object (contrary to solution 1, whare you are basically doing a switch based on the user type). Whether to choose 2 or 3 is more a matter of personal tastes.
However, I have a doubt: why do you pass a document to a create_document() method? I would go for a message name that best describes what it does. For example, in solution 3 (the one I like the most) I would go for:
Document>>create_document(User user)
{
this = user.create_document();
this->save();
}
and then
L1User>>create_document()
{
return new Document('L1');
}
or
Document>>create_document(User user)
{
this = new Document()
this = user.set_document_type(this);
this->save();
}
and then
L1User>>set_document_type(document)
{
document.setType('L1');
}
Edit: I kept thinking about this and there is actually a fourth solution. However the following approach works only if the status of a document doesn't change through its lifetime and you can map the DB field with a getter instead of a property. Since the document already knows the user and the status depends on the user, you can just delegate:
Document>>getStatus()
{
return this.user.getDocumentStatus();
}
HTH

Cannot retrieve user object from foreign key relationships using Linq to Entities statement

I'm trying to retrieve a user object from a foreign key reference but each time I try to do so nothing gets returned...
My table is set up like this:
FBUserID long,
UserID uniqueidentifier
so I have my repository try to get the User when it's provided the FBUserID:
public User getUserByFBuid(long uid)
{
User fbUser = null;
IEnumerable<FBuid> fbUids = _myEntitiesDB.FBuidSet.Where(user => user.FBUserID == uid);
fbUser = fbUids.FirstOrDefault().aspnet_Users;
return fbUser;
}
I've checked that the uid (FBUserID) passed in is correct, I've check that the UserID is matched up to the FBUserID. And I've also checked to make sure that fbUids.Count() > 0...
I've returned fbUids.FirstOrDefault().FBUserID and gotten the correct FBUserID, but any time I try to return the aspnet_Users or aspnet_Users.UserName, etc... I don't get anything returned. (I'm guessing it's getting an error for some reason)
I don't have debugging set up properly so that's probably why i'm having so much troubles... but so far all the checking I've done I've been doing return this.Json(/* stuff returned form the repository */) so that I can do an alert when it gets back to the javascript.
Anyone know why I would have troubles retrieving the user object from a foreign key relationship like that?
Or do you have any suggestions as to finding out what's wrong?
For now, with Entity Framework 1, you don't get automatic delayed loading, e.g. if you want to traverse from one entity to the next, you need to either do an .Include("OtherEntity") on your select to include those entities in the query, or you need to explicitly call .Load("OtherEntity") on your EntityContext to load that entity.
This was a design decision by the EF team not to support automagic deferred loading, since they considered it to be too dangerous; they wanted to make it clear and obvious to the user that he is also including / loading a second set of entities.
Due to high popular demand, the upcoming EF v4 (to be released with .NET 4.0 sometime towards the end of 2009) will support the automatic delayed loading - if you wish to use it. You need to explicitly enable it since it's off by default:
context.ContextOptions.DeferredLoadingEnabled = true;
See some articles on that new feature:
A Look at Lazy Loading in EF4
POCO Lazy Loading
Don't know if this is what you are asking but i do a join like so;
var votes = from av in dc.ArticleVotes
join v in dc.Votes on av.voteId equals v.id
where av.articleId == articleId
select v;
Did this help or am I off base?

Resources