Values for columns in ASP.NET Identity when creating manually - c#

Upon database initialization, I want to manually add an initial row to AspNetUsers:
insert AspNetUsers
(UserId,PersonId,UserName,NormalizedUserName,Email,NormalizedEmail,EmailConfirmed,PasswordHash,SecurityStamp,ConcurrencyStamp,PhoneNumber,PhoneNumberConfirmed,TwoFactorEnabled,LockoutEnd,LockoutEnabled,AccessFailedCount) values
(#userIdOut,#personIdOut,#adminUserName,upper(#adminUserName),#AdminEmail,upper(#AdminEmail),#true,null,newid(),null,#AdminPhone,#true,#false,null,#false,0)
However, when I do this, methods like FindByNameAsync don't work.
What I'm doing is:
Setting both NormalizedUserName and NormalizedEmail to upper case
Setting a random GUID for SecurityStamp
I'm handling the initial password on the client side.
What else should I be doing?

Related

How do I record the email address of a user that clicks a link in an email?

So I am sending my clients an email asking their level of satisfaction with my services. I want to record their answers in a database for analysis.
There are two buttons: thumbs up, thumbs down.
Both buttons take the user to a different webform in a web application.
Both webforms look identical (they just say thank you). But in the page load of the two different webforms, it will insert into my database if the user visited the thumbs up link, or the thumbs down link.
I want to be able to record which email address clicked on the link in my database as well.
Does anyone know how to do that?
This is the table i'm inserting into:
CREATE TABLE emails(
ID INT IDENTITY PRIMARY KEY,
Cust nvarchar(max) not null,
Rating nvarchar(max) not null,
Points int not null,
UpdateDate Datetime not null,
UpdateUser nvarchar(max) --This is the field I want to record the email address in!
);
You would have to add a GET parameter to the webform link, with the email address of the intended destination. Yes, this provides inherit security risks of not being able to securely identify the user, so you could also generate secret tokens to include with the request. However, due to how Email works, it may always be spoofed.
I.e.
http://contoso.com/Email/Subscription/?action=thumbsdown&email=barbara#contoso.com&token=7A8E1A6B-13F9-4292-BFB3-9D199E7FB96D
http://contoso.com/Email/Subscription/?action=thumbsup&email=barbara#contoso.com&token=7A8E1A6B-13F9-4292-BFB3-9D199E7FB96D
Alternatively, if you want to help provide basic security, make it an HTTPS request.
https://contoso.com/Email/Subscription/?action=thumbsdown&email=barbara#contoso.com&token=7A8E1A6B-13F9-4292-BFB3-9D199E7FB96D
https://contoso.com/Email/Subscription/?action=thumbsup&email=barbara#contoso.com&token=7A8E1A6B-13F9-4292-BFB3-9D199E7FB96D

how to use SCOPE_IDENTITY() not in insert

I want to get new id(Identity) before insert it. so, use this code:
select SCOPE_IDENTITY() AS NewId from tblName
but is get this:
1- Null
2- Null
COMPUTED COLUMN VERSION
You'll have to do this on the sql server to add the column.
alter table TableName add Code as (name + cast(id as varchar(200)))
Now your result set will always have Code as the name + id value, nice because this column will remain updated with that expression even if the field are changed (such as name).
Entity Framework Option (Less ideal)
You mentioned you are using Entity Framework. You need to concatenate the ID on a field within the same record during insert. There is no capacity in SQL (outside of Triggers) or Entity Framework to do what you are wanting in one step.
You need to do something like this:
var obj = new Thing{ field1= "some value", field2 = ""};
context.ThingTable.Add(obj);
context.SaveChanges();
obj.field2 = "bb" + obj.id; //after the first SaveChanges is when your id field would be populated
context.SaveChanges();
ORIGINAL Answer:
If you really must show this value to the user then the safe way to do it would be something like this:
begin tran
insert into test(test) values('this is something')
declare #pk int = scope_identity()
print #pk
You can now return the value in #pk and let the user determine if its acceptable. If it is then issue a COMMIT else issue the ROLLBACK command.
This however is not a very good design and I would think a misuse of the how identity values are generated. Also you should know if you perform a rollback, the ID that would of been used is lost and wont' be used again.
This is too verbose for a comment.
Consider how flawed this concept really is. The identity property is a running tally of the number of attempted inserts. You are wanting to return to the user the identity of a row that does not yet exist. Consider what would happen if you have values in the insert that cause it too fail. You already told the user what the identity would be but the insert failed so that identity has already been consumed. You should report to the user the value when the row actually exists, which is after the insert.
I can't understand why you want to show that identity to user before insert, I believe (as #SeanLange said) that is not custom and not useful, but if you insist I think you can do some infirm ways. One of them is
1) Insert new row then get ID with SCOPE_IDENTITY() and show to user
2) Then if you want to cancel operation delete the row and reset
identity (if necessary) with DBCC CHECKIDENT('[Table Name]', RESEED,
[Identity Seed]) method
Other way is not using the Identity column and manage id column by yourself and it must be clear this approach can't be work in concurrency scenarios.
I think perhaps you're confusing the SQL identity with a ORACLE sequence.
They work completely different.
With the ORACLE sequence you'll get the sequence before you insert the record.
With a SQL Identity, the last identity generated AFTER the insert in available via the SCOPE_IDENTITY() function.
If you really need to show the ID to the user before the insert, your best bet is to keep a counter in a separate table, and read the current value, and increment that by one. As long as "gaps" in the numbers aren't a problem.

ASP.NET Identity: Make other fields in AspNetUsers unique key

I'm working on the ASP.NET Identity. By default, the AspNetUsers table comes with a few columns such as: ID, UserName, HashPassword, Email, EmailConfirmed, Phone etc.
By default, the ID column is the Primary Key and UserName has the Unique Constraint.
How do I make other fields such as Email and/or Phone to have the same unique constraint as the UserName?
What I have done so far:
I manage to add the unique constraint to the database manually, however, unlike the UserName field, I was unable to do the validation on the application level. For example: The UserName field will display the error message "Name XXX is already taken" if the user tries to register an account with the same username.
To enforce uniqueness at the UserManager layer, you can implement your own IUserValidator and check for your custom uniqueness rules

Get application username for Audit table

I want to implement an audit table and I have no idea how am I supposed to get the username.
I am using C# and Sql Server. I have a Users table in my database. When I log in my windows form application I verify if the correct combination of username and password is used. But how do I inform the database of the current user? I thought of adding an extra column to my Users table in which to set on 1 the logged username. Is that a solution for single-user? But my application in supposed to support multi-user. What could be done in this case?
Depending on your authentication scheme, you need to get the the User name.
for thick client applications,
Environment.Username
and
System.Security.Principal.WindowsIdentity.GetCurrent()
are a couple of options.
typically for audit tables, there is a column called 'ModifiedByUser' where you can log the user name provided by the win form app.
create the nvarchar and datetime columns (if not already) in your audit table.
one will stored the user name and the other the datetime of the audit action.
in your code, whenever you want to add an entry to the audit table, get Environment.Username or System.Security.Principal.WindowsIdentity.GetCurrent(), along with DateTime.UtcNow and pass it on to be saved to the DB into the Audit table.
SQL Server knows who you are. You can simply use SUSER_SNAME() or/and ORIGINAL_LOGIN() function as a default value for the username column in your audit table. Same for the time of audit event, use GetDate() function. There is no need to send this information from the client.
This is a very open-ended question but I think I understand what you are trying to do. You have application-specfic users that are defined in a Users table (as opposed to using database users or active directory users) and you need to log specific information for auditing purposes or drive security based off of the logins. Is that correct?
This can be done, but the logic for it will need to be written in your application.
Let’s pretend we are writing a program to send out an invoice to a customer.
I used role based security where you can give users access to do specific tasks by granting them a role. For example, “Create New Invoice” could be a role. I usually have 2 tables for this:
SecuirtyRoleDefintion
SecurityRoleUsers
The fist table, Security Role Definition will have an ID column, the Description (“Create New Invoice”), and I usually have a Audit column to indicate if this action needs to be logged for Audit.
The second table, SecurityRoleUsers, is where I define if a user has permission to execute that role. Columns are usually something like this: a unique ID, User ID (foreign key to the Users table), RoleID (foreign key to SecurityRoleDefintion)
Now in your application we need a class to check if a user has a role. It needs to take in the role ID (or name) and the user ID. Example: public bool IsUserAuthorized(int RoleID, int UserID)
This method can run a query on your SecurityRoleUsers table to see if the user is in the table for that role. If so, it returns true. If not, it returns false.
Now back in the application when user click the “Create New Invoice” button it runs the IsUserAuthorized() method to check if a user can perform the operation.
If creating an audit log is necessary, you could do something similar. After the security check is done for “Create New Invoice” you can check to see if the Role needs to be audit logged, if so then write to an Audit table.
DECLARE #username varchar(128)
SET #username = CONVERT(VarChar(128), CONTEXT_INFO());
PRINT #username
DECLARE #ID_User int
SET #ID_User = ( SELECT Users.ID_User
FROM Users
WHERE Users.Username=#username )
PRINT #ID_User
This is how I solved it. I inserted this piece of code in each update trigger.

Design Implementation SQL tables

I am new to SQL and been given a task. Following are the details:
What I have:
A C# desktop application for User login and view user status (only two options: user logs in and check status of all users that are dummy created)
A table named USER containing
id
username
datecreated
A table named LOGINSTAT containing
id
username
Logtime
logDate
What I have to implement
I have to save time and date when ever user logs in in LOGINSTAT table using SQL.
My question
My question is how can I implement that. I can do the coding part but I am interested in getting some good advice to implement it. I think of it as a formal way as I know to do it:
when user logs in insert values into the login table giving all the required values.
BUT
I think that might be a bit odd. Some of my friends said you may be able to implement it by use of foreign key and primary keys, but the problem lies that the user may log in many time in a day. How to keep track of login time and date in that case?
You don't need username in your LOGINSTAT table.
You'll probably want the LOGINSTAT to include:
id
u_id
loginDateTime
id is the unique ID of every login
u_id is a foreign key from the id in users that matches your log event to a user
loginDateTime is a datetime that will give you both your log date and log time in one column
What is unique in LOGINSTAT? Not user by itself, but ID+LogDate+LogTime should be. That would be your primary key.
The only foreign key is in LOGINSTAT: ID, which references the ID in the USER table.
Values in a PRIMARY KEY column (eg. USER.id) must be unique from one another.
Values in a FOREIGN KEY column in another table referencing that primary key (eg. LOGINSTAT.id referencing USER.id) do not need to be unique - you can have multiple records in a table have the same foreign key column reference the same primary key.

Categories

Resources