UserID from AuthenticationStateProvider appears empty - asp.net-core

I am using AspNetCore Identity and trying to get the UserID of the currently logged in user using AuthenticationStateProvider. I am logging to the console the output however, the username outputs fine but the ID appears empty. The ID field is not empty in the db table. When printing all the claims the subs field seems to be the correct ID. Am I incorrectly retrieving the ID? The approach to retrieve the ID was suggested from another post I found; code is shown below. How might I retrieve the sub value which is the userID, in my page using AuthenticationStateProvider? Thanks in advance.
Retrieving UserID
var user = (await ASP.GetAuthenticationStateAsync()).User;
var UserStringId = user.FindFirst(c => c.Type.Equals(user.Identity.Name))?.Value;
Browser console output
USER ID: blazor.webassembly.js:1
NAME: user4#gmail.com
Sub is correct ID when looping through Claims
var user = (await ASP.GetAuthenticationStateAsync()).User;
var item = user.Claims;
foreach(var x in item)
{
Console.WriteLine(x);
}
Browser console output
s_hash: EQ_bVJS8n32qtUam0wZ1MA
sid: 2E6B597CC9644CFEFDD627532B761F02
sub: 5685a830-cb82-4b60-b459-c0852cc74563 // trying to retrieve this ID
//...
preferred_username: user4#gmail.com
name: user4#gmail.com

Try:
user.FindFirst(c => c.Type == "sub")?.Value

Related

Suitescript: copying sublist data from one record to another

I have a before load user event function on an invoice record that create a button called 'create vendor bill'.
When this button is pressed, a new vendor bill record is opened. The UE script:
/**
*#NApiVersion 2.x
*#NScriptType UserEventScript
*/
define([
"N/url",
"N/record",
"N/runtime",
"N/ui/serverWidget",
"N/redirect",
], function (url, record, runtime, serverWidget, redirect) {
var exports = {};
/**
* #param {UserEventContext.beforeLoad} context
*/
function beforeLoad(context) {
if (
context.type == context.UserEventType.EDIT ||
context.type == context.UserEventType.VIEW
) {
var record = context.newRecord;
var recordId = record.id;
var recordType = record.type;
var customer = record.getValue({ fieldId: "entity" });
log.debug("entity", customer);
var scriptObj = runtime.getCurrentScript();
var customForm = scriptObj.getParameter({
name: "custscript_custom_form_vb",
});
var recordSublist = record.getSublist({ sublistId: "item" });
log.debug("item", recordSublist);
var form = context.form;
log.debug("form", form);
var userVarStr = record;
log.debug("uservarstr", userVarStr);
var userVarURL = url.resolveRecord({
recordType: "vendorbill",
params: {
entity: parseInt(customer),
supportcase: recordId,
cf: parseInt(customForm),
},
});
form.addButton({
id: "custpage_button_test",
label: "Create Vendor Bill",
functionName: "getDetails('" + userVarURL + "')",
});
}
}
exports.beforeLoad = beforeLoad;
return exports;
});
Once the page redirects to the vendor bill form, a client script (deployed on the form), sets the field values on the body of the vendor bill using the parameters passed in the url
This is working as expected.
Where I am getting stuck is trying to work out how to pass the 'item' sublist values to from the invoice to the vendor bill?
Would I pass this as an array?
From what I understand, there is a limit to the number of characters that can be passed via the url.
I can't find anything online or in the Netsuite documentation that deals with passing sublist values between records
For starters I would want to see the Client Script.
One option would be to only pass the Invoice Record ID and Type. Then you can create a Suitelet to be used as a proxy and get the sublist data by a saved search.
Something to keep in mind is that if the sublist is very very long you may reach a execution timeout so you may want to consider triggering a MapReduce script to populate the sublist again you would pass it the recType and ID of the invoice and vendor bill and then use a saved search to get the data.
There are other approaches but I would need to see the client script.

Getting individual question scores(numbers) from Google forms to a google spreadsheet

I have a google form which is basically an assessment for students. Each question carries 1 point. When I connect my form to a specific spreadsheet, I get the total score of the student e.g 24/30
What I want to do:
Along with the total score, we want to get each question's score to go to the spreadsheet. Here is what we are trying to have:
I have no idea what to do. Please guide. Thanks
You can try with Apps Script. I tested the following script that can give you an idea on how to achieve this.
const TARGET_SPREADSHEET_ID = "spreadsheetID"; //Change according to your needs
const TARGET_SHEET_NAME = "sheetName"; //Change according to your needs
const SOURCE_FORM_ID = "formID"; //Change according to your needs
//Run this function only one time, this will create a trigger that will run function "onFormSubmitTrigger" whenever a student submits a response.
function installOnFormSubmitTrigger() {
const form = FormApp.openById(SOURCE_FORM_ID);
ScriptApp.newTrigger("onFormSubmitTrigger")
.forForm(form)
.onFormSubmit()
.create();
}
function onFormSubmitTrigger(e) {
const targetSpreadsheet = SpreadsheetApp.openById(TARGET_SPREADSHEET_ID);
const targetSheet = targetSpreadsheet.getSheetByName(TARGET_SHEET_NAME);
//GETTING RESPONSES
var itemResponses = e.response.getItemResponses();
var responses = itemResponses.map(itemResponse => itemResponse.getResponse()); //Get responses
var name = responses.splice(0,1); //extracting first element ("Full Name") of responses
//GETTING SCORES
var itemScores = e.response.getGradableItemResponses();
var scores = itemScores.map(itemScore => itemScore.getScore()); // Get response score
scores.splice(0,1); //removing score for the first element ("Full Name")
var newArr = name.concat(scores); //combining name and scores in one array
//newArr.splice (1,0,""); //you can add this line to insert blank between "Student Name" and "Q1"
targetSheet.appendRow(newArr); //Append scores to the sheet
}
Test the script by submitting a form and the target sheet should show students names and the score for each question they answered. If you have any questions let me know.

How to manually hash a password using Asp.Net Core 2.2 / IdentityServer4 / SP.NET Core Identity

I am migrating tens of thousands of users from an old website that didn't have a password in the database to this new web application, however, when I try to import the users using the async method, it ends up taking several days to the point where I just ended up cancelling it after a few days.
Now I have resorted to just creating new users directly from _context.Users.Add and assigning their roles, which i can do without a problem.. However, I can't seem to figure out how to create a generic password (all the same password) as these users will just be given a password to view a livestream (doesn't need to be super secure), but I still need the security part for the admin accounts that handle other stuff through the client/admin side UI. If a user signs in, I will have it automatically enter the default password for them.
For some reason though, I cannot get the password hasher to work correctly, as when I sign in, it says that the password is wrong...
This is what I'm using to generate the password and create the users...
var appUser = new ApplicationUser() {
Id = GenerateId(),
AccessFailedCount = 0,
Email = user[1],
PasswordHash = "",
FullName = "Standard User",
UserName = user[1],
PhoneNumber = user[8],
FirstName = user[2],
LastName = user[3],
JoinMailingList = user[4],
Country = user[5],
City = user[6],
StateRegion = user[7]
};
_context.Users.Add(appUser);
var options = new PasswordHasherOptions();
options.CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2;
var hasher = new PasswordHasher < ApplicationUser > ();
appUser.PasswordHash = hasher.HashPassword(appUser, "Default8!");
var role = _context.Roles.FirstOrDefault(r => r.Name == "user");
if (role != null) {
var userRole = new IdentityUserRole < string > ();
userRole.RoleId = role.Id;
userRole.UserId = appUser.Id;
_context.UserRoles.Add(userRole);
}
}
_context.SaveChanges();
Can anyone help me out with how I'm supposed to Hash a password to store into the database?
If a user signs in, I will have it automatically enter the default password for them.
If you are using .net core Identity, you can use UserManager.CreateAsync to create the specified user in the backing store with given password:
public virtual System.Threading.Tasks.Task<Microsoft.AspNetCore.Identity.IdentityResult> CreateAsync (TUser user, string password);
Code below is for your reference:
var user = new ApplicationUser { UserName = "wx2#hotmail.com", Email = "wx2#hotmail.com" };
var result = await _userManager.CreateAsync(user, "YourPassWord");
if (result.Succeeded)
{
}
The Identity system will help create the password hash and store in the database . If you still need to manually hash the password , see IPasswordHasher interface .
Edit:
If you want to directly insert/update via database context, you should set correct NormalizedUserName and SecurityStamp to make the system work:
ApplicationUser applicationUser = new ApplicationUser();
Guid guid = Guid.NewGuid();
applicationUser.Id = guid.ToString();
applicationUser.UserName = "wx#hotmail.com";
applicationUser.Email = "wx#hotmail.com";
applicationUser.NormalizedUserName = "wx#hotmail.com";
_context.Users.Add(applicationUser);
var hasedPassword = _passwordHasher.HashPassword(applicationUser, "YourPassword");
applicationUser.SecurityStamp = Guid.NewGuid().ToString();
applicationUser.PasswordHash = hasedPassword;
_context.SaveChanges();
As an addition, if you just want to Update the Password field of an given User:
var oldUser = await _userManager.GetUserAsync(User);
var result = await _userManager.ChangePasswordAsync(oldUser,
updateUserVm.CurrentPassword,
updateUserVm.NewPassword);
And an example to the Question "How I'm supposed to Hash a password?". You could Hash a registered Users Password with the UserManager-Referenced PasswordHasher like this:
ApplicationUser user = _userManager.Users...;
user.PasswordHash = _userManager.PasswordHasher.HashPassword(user, newPassword);
I write my class PasswordHasher based on .net6 PasswordHasher docs latest version (V3) in this stackoverflow answer :
https://stackoverflow.com/a/72429730/9875486

How to check if user is part of an AD group? (even group within a group)

I need to check if users logging into the console application I am making are part of a DL (let's call it DL-A).
Some users aren't directly part of DL-A, but of other DLs that are a member of DL-A. The code that I have working only checks the groups of which the user is directly a member of. How do I check this?
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain);
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, username);
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, "DL-A");
if (user != null)
{
if (user.IsMemberOf(group))
{
...
}
}
One way you can see if the user is a member of a nested group is get all the users from a group recursively. I am using user and group from your code:
....
if (group != null)
{
var users = group.GetMembers(true); //this will get nested users
var contains = users.Contains(user);
if (contains)
{
//user found
}
}
...

How to handle NHibernate LINQ empty result set?

I want to retrieve list of roles for a logged in user.
Following is a code segment that reads user roles from the database.
ISession session = NHibernateHelper.GetCurrentSession();
var data = from s in session.Linq<ApplicationUserRole>()
where s.AppUser.ID = 1
select s.Role.Name;
List<Role> list = data.ToList();
AppUser: User entity
Role: Role entity.
As there are no data in the database for user id 1, it doesn't return anything.
Return type data is NHibernate.Linq.Query and it is not null.
It throws following error when I attempt to convert it to ToList();
"Index was out of range. Must be
non-negative and less than the size of
the collection. Parameter name: index"
How do I handle empty result sets?
This should work...
List<Role> list = data.Any() ? data.ToList() : new List<Role>();