Create a user with Active Directory - c#

I'm trying to create a user in Active Directory, using a function I adapted from some sample code I have found.
public bool crearUsuario(string usu, string pass, string path)
{
string path = #"LDAP://" + path;
//string oGUID = string.Empty;
try {
DirectoryEntry entrada = new DirectoryEntry(path);
DirectoryEntry nuevoUsuario = entrada.Children.Add("CN=" + usu, "users");
nuevoUsuario.Properties["samAccountName"].Value = usu;
nuevoUsuario.CommitChanges();
//oGUID = nuevoUsuario.Guid.ToString();
nuevoUsuario.Invoke("SetPassword", new object[] { pass });
nuevoUsuario.CommitChanges();
entrada.Close();
nuevoUsuario.Close();
return true;
}
catch (System.DirectoryServices.DirectoryServicesCOMException E)
{
//E.Message.ToString();
return false;
}
//return oGUID;
}
The original code returned a string (oGUID), but I only need a boolean.
My question is, why do they use that string? I only need true or false values, so I don't know if I need to return a string instead of a boolean value.

String seems an odd choice to me, also: I would have returned the raw Guid type. But the reason to return a string, guid, or other key, is there's an expectation you'll want to do something with that user account after you create it. Returning the new key as part of the original creation function is very likely to save you some work later.
If you know you won't be in that situation, it's perfectly fine to just return true/false... keeping in mind the comment on the question about letting the exception bubble up also has merit.

Related

C# - Using File.Exists, when file DOESN'T exist does not run the last else statement

Super new to C#. I'm having an input get split and then find an ID from the pointsTarget var.
When the file DOES exist, it seems that the line
else if (File.Exists(filePath+userId+txt))
returns true;
because it runs just fine and sets the argument "addPointsCompleted" to TRUE. It works just how I would expect. But when the file does NOT exist, I want it to return false and run the last else statement:
CPH.SetArgument("missing", "True");
and set "missing" to TRUE.
I feel like there is something wrong with the way I put in the if/else if/else statement because I get an error :
"System.IO.FileNotFoundException: Could not find file 'E:\Users\Troy\Documents\Stuff\PointNames\Test.txt'.
using System;
using System.IO;
public class CPHInline
{
public bool Execute()
{
string rawInput = args["rawInput"].ToString();
string[] split= rawInput.Split('+');
var pointsTarget = split[0].ToString();
var addPoints = split[1].ToString();
CPH.LogInfo($"pointsTarget is {pointsTarget}");
CPH.LogInfo($"addPoints is {addPoints}");
var user = args["user"].ToString();
CPH.SetArgument("pointsTarget", pointsTarget);
string userPath = #"E:/Users/Troy/Documents/Stuff/PointNames/";
string filePath = #"E:/Users/Troy/Documents/Stuff/PointIDs/";
string txt = ".txt";
var userId = File.ReadAllText(userPath+pointsTarget+txt);
CPH.LogInfo($"userId is {userId}");
if (user == pointsTarget)
{
CPH.SetArgument("corrupt", "True");
}
else if (File.Exists(filePath+userId+txt))
{
//DO THIS
string fileName = filePath+userId+txt;
string points = File.ReadAllText(fileName);
int x = Convert.ToInt32(points);
int y = Convert.ToInt32(addPoints);
int sum = x + y;
String newPoints;
newPoints = sum.ToString();
File.WriteAllText(fileName, newPoints);
CPH.SetArgument("newPoints", newPoints);
CPH.SetArgument("addPointsCompleted", "True");
}
else
{
//do this
CPH.SetArgument("missing", "True");
}
return true;
}
}
I tried looking around, but all the issues are from people where the file DOES exist and they can't find it. My problem is kind of the opposite.
I feel like there is something wrong with the way I put in the if/else if/else statement because I get an error "System.IO.FileNotFoundException: Could not find file 'E:\Users\Troy\Documents\Stuff\PointNames\Test.txt'.
This is a good opportunity for you to start familiarizing yourself with using a debugger to step through the code and observe its behavior. Because the problem has nothing to do with your if structure. It's happening before your if block. Right here:
var userId = File.ReadAllText(userPath+pointsTarget+txt);
Look at the error message. It's trying to read a file in the "PointNames" folder. Which is in your userPath variable:
string userPath = #"E:/Users/Troy/Documents/Stuff/PointNames/";
Which is only ever used in that one line of code that tries to read a file. And File.ReadAllText will throw a FileNotFoundException if the file is not found.
It seems you're already aware of how to check if a file exists. So why not apply that here? For example:
var userId = string.Empty;
if (File.Exists(userPath+pointsTarget+txt))
{
userId = File.ReadAllText(userPath+pointsTarget+txt);
}
else
{
// handle the error in some way
}

Storing and Retrieving User Credentials in Xamarin iOS

I have a Xamarin.iOS application that requires users to log-in in order to view content. I have two text fields, one for username and one for password. Once a user has logged in and the API has returned success. how can I save the users credentials so when they launch the app they get signed in automatically?
I tried this, however, I don't know how to retrieve the values or re-save credentials if user logs out
void StoreKeysInKeychain(string key, string value)
{
var s = new SecRecord(SecKind.GenericPassword)
{
ValueData = NSData.FromString(value),
Generic = NSData.FromString(key)
};
var err = SecKeyChain.Add(s);
}
Thanks.
You can install this plugin and all of the work is already done for you: https://github.com/sameerkapps/SecureStorage, nuget: https://www.nuget.org/packages/sameerIOTApps.Plugin.SecureStorage/.
If you use the plugin it is as simple as:
CrossSecureStorage.Current.SetValue("SessionToken", "1234567890");
var sessionToken = CrossSecureStorage.Current.GetValue ("SessionToken");
If you don't want to use it, then look into github repo and see how they did it for iOS:
https://github.com/sameerkapps/SecureStorage/blob/master/SecureStorage/Plugin.SecureStorage.iOSUnified/SecureStorageImplementation.cs
public override string GetValue(string key, string defaultValue)
{
SecStatusCode ssc;
var found = GetRecord(key, out ssc);
if (ssc == SecStatusCode.Success)
{
return found.ValueData.ToString();
}
return defaultValue;
}
private SecRecord GetRecord(string key, out SecStatusCode ssc)
{
var sr = new SecRecord(SecKind.GenericPassword);
sr.Account = key;
return SecKeyChain.QueryAsRecord(sr, out ssc);
}
Better to use iOS default NSUserDefaults.StandardUserDefaults to store your credentials.
Check for stored value in Login ViewController, if it doesn't exist then after successful login set the user name and password to "GetStoredCredentials" else fetch the saved credentials and use.
public String GetStoredCredentials
{
get {
string value = NSUserDefaults.StandardUserDefaults.StringForKey("Key");
if (value == null)
return "";
else
return value;
}
set {
NSUserDefaults.StandardUserDefaults.SetString(value.ToString (), "Key");
NSUserDefaults.StandardUserDefaults.Synchronize ();
}
}
Either you can save as string array or comma seperated value.
Let me know for any further assistance.
For your refrence : https://developer.xamarin.com/guides/ios/application_fundamentals/user-defaults/

Appending chat history and insert it into the same file

I have a case that I need to log the chat history (I am capable of doing this already) and I need it to be logged in a text file (able to log it already).
The problem is the file is being accessed all over again so I need to somewhere store the filename of the file somewhere else, right now I have this code:
public async Task LogAsync(IActivity activity)
{
var conversation = "";
var convActivity = "";
var ctr = 0;
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\r\n Message: {activity.AsMessageActivity()?.Attachments}\r\n ";
fileName = "test";
await LogActivity(fileName, conversation);
}
The LogActivity is the one handling the append of the file. So what I need is I want the unique fileName to be instantiated once while appending the file all over again or rather while continuously accessing this method.
Or is there a way to log the chat history of bot once like if a Context.Done was called or before it?
Or the inefficient way I am thinking of was making use of .From.Name and .Recipient.Name
So the result will be:
if (activity.From.Name.ToLower().ToString() == "user")
{
name.Value = $"{activity.From.Name.ToString()}";
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\n Message: {activity.AsMessageActivity()?.Text}\n";
}
else
{
name.Value = $"{activity.Recipient.Name.ToString()}";
conversation = $"From: {activity.From.Name}\r\n To: {activity.Recipient.Name}\r\n Message: {activity.AsMessageActivity()?.Text}\r\n ";
}
await LogActivity(name.Value, conversation);
If I understand correctly, you just want to persist a value throughout a conversation; in this case a filename.
If that's correct, then you can store it in PrivateConversationData which lives in thecontext.
For example:
context.PrivateConversationData.SetValue<string>("log_filename", "log-name-here.txt");
For an example, check here: https://www.robinosborne.co.uk/2016/08/08/persisting-data-within-a-conversation-with-botframeworks-dialogs/
For a full example about persisting the whole conversation, this might also help: https://www.robinosborne.co.uk/2016/11/22/transcribing-messages-in-botframework/
Okay, rposbo's answer also works if you have your own logger (that's what I observed, or maybe if you can implement it the other way around, you can use it, it's up to you) that will persist on each every conversation you have with your bot, see the link he provided on how to persist the whole conversation. As for my end, I used dictionary to store the filename. So down below is what I did
public string _Name { get { return name; } }
string name;
public static Dictionary<string, string> fileName = new Dictionary<string, string>();
public void SetFileName(string _fileName)
{
var isCached = fileName.TryGetValue("filename", out name);
if (!isCached)
{
name = $"{_fileName}_{DateTime.Now.Ticks}";
fileName.Add("filename", name);
}
}
Btw, can I accept two answers? since rposbo's answer also works, but it just doesn't fit for me.

How do I update a field in the database before my transaction is committed?

I am working on a password change method, this view is enforced by one of many conditions. The first condition is if the LastLoggedin field in the database is null. I have this field set to null in my test database to force the password change events.
I have coded a method to change the password after performing some tests, but I cannot get past the first test because the controller method that the click event calls returns the user back to the log on method, which in turns checks the LastLoggedin field in the database which is still null because I have not yet logged in. I tried to change that value from within my change password method using the following code:
public bool SavePassword(UserModel user, PasswordRecoveryModel password)
{
try
{
string newPass = password.PasswordNew;
string newHash = PasswordManager.EncryptPassword(newPass);
User domainObject = UnitOfWork.UserRepository.GetItem(user.EntityId);
bool hasUsedPassword = UnitOfWork.UserRepository.HasHadPassword(domainObject, newHash, DateTime.Now.AddMonths(-6));
if (hasUsedPassword.Equals(true))
{
return true;
}
User lastLogged = UnitOfWork.UserRepository.GetItem(user.EntityId);
lastLogged.LastLoggedIn = DateTime.Now;
lastLogged.VerifiedOn = DateTime.Now;
UnitOfWork.UserRepository.Update(lastLogged);
lastLogged.VerifiedOn.Equals(DateTime.Now);
lastLogged.LastLoggedIn.Equals(DateTime.Now);
user.Password = newHash;
user = SaveModel(UnitOfWork.UserRepository,
user,
Mapper.User.ModelToDomain,
Mapper.User.DomainToUserModel);
CommitTransaction();
return false;
}
catch (Exception ex)
{
OnServiceException(ex);
throw;
}
}
But I am still not getting anything other than the new password saved in the database, I am verifying this by running a query on my username. How do I update this field so I can get by this test on password change, and is it even acceptable to do this? In our old product it was done in a very complex manner creating a temporary user object ant using that to get past the test and on to the next test. I am trying to simplify the process.
I am new to MVC and programming in general any help would be appreciated.
EDIT found my problem, as usual over thinking the issue, here is the updated code:
if (hasUsedPassword.Equals(true))
{
return false;
}
user.LastLoggedIn = DateTime.Now.ToString();
user.Password = newHash;
user = SaveModel(UnitOfWork.UserRepository,
user,
Mapper.User.ModelToDomain,
Mapper.User.DomainToUserModel);
CommitTransaction();
return true;

How to check if cookies are empty or not

I need to check if cookie is present with value or not. But I wonder if there is some quick and good way of doing so since if I need to check 3 cookies it seems bad to check with if or try.
Why it does not assign empty string to my variable if cookie is not present? Instead it shows Object reference not set to an instance of an object.
My code (it works, but it seems too big for this task, I think there should be a better way of doing this)
// First I need to asign empty variables and I don't like this
string randomHash = string.Empty;
string browserHash = string.Empty;
int userID = 0;
// Second I need to add this huge block of try/catch just to get cookies
// It's fine since I need all three values in this example so if one fails all fails
try
{
randomHash = Convert.ToString(Request.Cookies["randomHash"].Value);
browserHash = Convert.ToString(Request.Cookies["browserHash"].Value);
userID = Convert.ToInt32(Request.Cookies["userID"].Value);
}
catch
{
// And of course there is nothing to catch here
}
As you can see I have this huge block just to get cookies. What I would like is something like this:
// Gives value on success, null on cookie that is not found
string randomHash = Convert.ToString(Request.Cookies["randomHash"].Value);
string browserHash = Convert.ToString(Request.Cookies["browserHash"].Value);
int userID = Convert.ToInt32(Request.Cookies["userID"].Value);
Edit
Maybe I can somehow override the .Value method to my liking?
Just check if the cookie is null:
if(Request.Cookies["randomHash"] != null)
{
//do something
}
NOTE: The "Better" way of doing this is to write good code that is both readable and reliable. It doesn't assign empty string because this is not how C# works, you are trying to call the Value property on a null object (HttpCookie) - you cannot use null objects because there is nothing to use.
Converting to an int you still need to avoid parse errors, but you can use this built in method:
int.TryParse(cookieString, out userID);
which brings on another point? Why are you storing the userID in a cookie? this can be changed by the end user - I don't know how you plan on using this but would I be right to assume this is a big security hole?
or with a little helper function:
public string GetCookieValueOrDefault(string cookieName)
{
HttpCookie cookie = Request.Cookies[cookieName];
if(cookie == null)
{
return "";
}
return cookie.Value;
}
then...
string randomHash = GetCookieValueOrDefault("randomHash");
Or with an Extension method:
public static string GetValueOrDefault(this HttpCookie cookie)
{
if(cookie == null)
{
return "";
}
return cookie.Value;
}
then...
string randomHash = Request.Cookies["randomHash"].GetValueOrDefault();

Categories

Resources