Password change every 90 days in MVC and SQL Server - c#

I want a method to ask the user to change his password after having it for 90 days.
I have something like this
ALTER PROCEDURE [dbo].[spRecoverPassword]
(
#sUsername varchar(50),
#sPassword varchar(100),
#sPasswordSalt varchar (128)
)
AS
BEGIN
SET NOCOUNT ON;
if (exists (select 1
from USER
where Username = #sUsername))
begin
update USER
set Password_Salt = #sPasswordSalt,
Password = #sPassword,
where Username = #sUsername;
select 1;
end
else
begin
select -1;
end
END
Then I have a method to call this stored procedure, from ASP.NET MVC. And somehow I would like to check the date that the password was last changed and do so that if that date is 90 days higher than today it will redirect it to the recover pass again. How should I do this?
Thanks

Add a new column in users Table to save last modified date of password.
on Get method calculate the difference between Last modified date of password and today's date. and do what you want to do.

Very easy:
add a date field in USER table for example last_changed.
update last_changed with now() in the query
check days difference DATEDIFF(now(),last_changed)>90

Related

Stored Procedure for Employee Clock table

I have an Employee Clock table with these columns:
EmpID nvarchar(200) (FK)
EmpName nvarchar(100)
Password nvarchar(100)
punchTime datetime
punchType bit
I am going to design an application (in C#) that lets employees check in and check out.
The process will be: when an employee wants to check in, they will input their EmpID and Password, then hit Enter. In the backend, the app will run a stored procedure that enters the values of EmpID, Password, EmpName (will be retrieved from Employee table based on EmpID), punchTime and punchType (= 1 for Check In, 0 for Check Out).
The process of checking out is exactly same as checking in, the employee will just need to enter their EmpID and Password, then hit Enter.
I am looking for a stored procedure that could do something like:
when keyEnter.hit (from C#) => run the stored procedure:
if max(EmpID) has punch = 1 (the employee already checked in), then set punch = 0 with provided punchTime and EmpID
else if max(EmpID) has punch = 0 (the employee already checked out), then set punch = 1 with punchTime and EmpID
I have been messing around with the stored procedure, but did not get the result as I wanted. I appreciate any help.
Having worked on a clock in/out system, I can warn you now that it is not as simple as you think. If a user misses a clock in or out, you will have to manually insert a new record and then correct all the punch types after that point in time... get ready to write that stored procedure before you move to production! Also, I am going to ignore the odd format of the EmployeeClock table - why are you storing the password in it? Regardless, your question is about a stored procedure so let's deal with that.
I assume that there is an Employee table that stores the name and the password. The password should be validated before any record is created in the EmployeeClock so I will do that. Next, you should see if there is an existing record in EmployeeClock for the employee - it could be the first time they ever log in. Finally, if there is an existing record in EmployeeClock, create a new record and flip the bit for the punchType. Finally, you may want to return a result so you know whether it was successful or not. Additionally, you may want to log the information from a bad attempt somewhere (which I will not show). Putting this all together:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE dbo.EmployeeClockInOut
#EmpID NVARCHAR(200),
#Password NVARCHAR(100)
AS
BEGIN
SET NOCOUNT ON;
-- you should make sure that the employee password is
-- correct before you do anything... assume you have a
-- Employee table that you can look up
IF EXISTS(SELECT 1 FROM dbo.Employee WHERE EmpId = #EmpID AND [Password] = #Password)
BEGIN
-- have they ever clocked in?
IF EXISTS(SELECT 1 FROM dbo.EmployeeClock WHERE EmpID = #EmpID)
BEGIN
-- they have clocked in at least once - flip the punch type
-- from their last clock in
INSERT INTO dbo.EmployeeClock(EmpID, EmpName, [Password], punchTime, punchType)
SELECT TOP(1) #EmpID, e.EmpName, #Password, GETDATE(),
CASE WHEN c.punchType = 1 THEN 0 ELSE 1 END
FROM dbo.Employee AS e
INNER JOIN dbo.EmployeeClock AS c ON e.EmpID = c.EmpID
WHERE e.EmpID = #EmpID
ORDER BY c.punchTime DESC;
END
ELSE
BEGIN
-- there is no clock in record - create first clock in entry
INSERT INTO dbo.EmployeeClock(EmpID, EmpName, [Password], punchTime, punchType)
SELECT #EmpID, EmpName, #Password, GETDATE(), 1 FROM dbo.Employee WHERE EmpID = #EmpID
END
SELECT 'Clock in/out successful' AS [Result];
END
ELSE
BEGIN
-- log the attempt or alert the user...
SELECT 'EmpID or Password was invalid' AS [Result];
END
END
GO

Comparing current date in stored procedure

I am trying to check in a stored procedure a date in table if it is equal to Today's date.
Code is
DECLARE #p0 datetime
Set #p0 =GETDATE()
Select * from testtable
where dateCol=#p0
This doesn't work it just gives empty rows. How can I accomplish that? Thanks
If dateCol is just the date, not DATETIME, you can use:
SELECT *
FROM Table
WHERE dateCol = CAST(GETDATE() AS DATE)
You need:
SET #p0 = CONVERT(CHAR(10),GETDATE(),103)
GETDATE() returns the date and time. You probably have records with todays date but not at this exact time.
Also you don't really need to store it in #p0. You could use the expression directly in the WHERE clause.

Custom SQL Function For Generating Year Wise Client Code

SQL Function For Generating Year Wise Client Code:
The following sql function will generate year wise client code based on server-date. such as for 2012 client the codes will be
CL12-00001, CL12-00002,....and for 2013 the codes will be
CL13-00001, CL13-00002,....etc.
(Here CL means client, 12 for year 2012, 13 for year 2013.)
CREATE function [dbo].[GenClientCode]()
returns nvarchar(20)
as
begin
Declare #Code nvarchar(20), #cyear nvarchar(2);
SET #cyear= ( SUBSTRING(CONVERT(nvarchar(2),DATEPART(year, sysdatetime())),3,2));
SET #Code= (Select MAX(CONVERT(INT, SUBSTRING(ClientCode,6, LEN(ClientCode))))+1
from tblClientInfo WHERE SUBSTRING(ClientCode,3,2)=#cyear);
--assume the code format is like CL12-00001, here 12 for year 2012
if (#Code is null or #Code='')
set #Code='00001'
else if LEN(#Code)=1
set #Code='0000'+ CONVERT(nvarchar(1),#Code);
else if LEN(#Code)=2
set #Code='000'+ CONVERT(nvarchar(2),#Code);
else if LEN(#Code)=3
set #Code='00'+ CONVERT(nvarchar(3),#Code);
else if LEN(#Code)=4
set #Code='0'+ CONVERT(nvarchar(4),#Code);
set #Code='CL'+#cyear+'-'+ CONVERT(nvarchar(10),#Code);
return #Code;
end
Is my function is optimum or not?
Your idea has several obvious problems such as "what happens in the year 2100?" and "what happens if there more than 99999 codes in a year?". Also there are a few less obvious issues such as "what happens if two codes are requested at nearly the same time?" and the fact that you're doing a query off a substring which means that SQL Server can't use an index (meaning your performance may be bad).
"How do I get a 2-digit year?" and "how do I left-pad strings?" seems to have been answered by Kaf.
If you're on SQL Server 2012, I would suggest looking into sequences. If you're on an earlier version, I would suggest putting a new table into your database with two integer fields representing the year and the next available number for that year and then changing your scalar function to a stored procedure that is able to query and update that table using an exclusive lock. This would allow you to find the next number quickly using an indexed small table rather than doing a table scan over what I assume to be a large table. Also this would help protect you from possible duplicates if your system is under pressure.
Getting MAX+1 for the next record is not very accurate. Better solution would be to have an auto incremented identity(1,1) column, say IdCol and a date column, say dateCol. Then you can form your specific code on SELECT as;
SELECT 'CL' + RIGHT(DATEPART(yy,dateCol),2) + '-' +
RIGHT('00000' + CONVERT(VARCHAR(5),idCol),5)
--Note:Max clients 99999
However, your function also can be optimised as;
CREATE function [dbo].[GenClientCode]()
returns varchar(20)
AS
BEGIN
Declare #code varchar(20), #cyear varchar(2);
SELECT #cyear = RIGHT(DATEPART(yy,Getdate()),2);
SELECT #code = ISNULL( MAX(
SUBSTRING(ClientCode, CHARINDEX('-', ClientCode) + 1,
LEN(ClientCode))
), 0)+1
FROM tblClientInfo
WHERE SUBSTRING(ClientCode,3,2) = #cyear
RETURN 'CL' + #cyear + '-' + RIGHT('00000' + #code, 5)
END

Build up list first, or query for every record? (Have to check for duplicates)

I'm doing some web scraping to build up a personal SQL database. As I'm looping through the web requests, I'm adding records. The only thing is, duplicates sometimes appear in the web requests and I want to make sure to only add a record if it doesn't already exist in my database. I gather this can be done by performing an SQL query before every insert to make sure that record hasn't already been added, but is this the best way to do it? Would it make more sense to build up a Generic.List first, and then do all my database inserts at the end?
You can create a stored procedure that will attempt to update a record and then insert if the update query did not update any rows. This will minimize the number of queries that need to be run and prevent checking for the row's existence. A little bit of Googling found this. The second option looks like it might be what you are looking for.
/*
Same SP is used to INSERT as well as UPDATE a table.
Here we are avoid unnecessary checking of whether the record exists or not.
Instead try to Update directly. If there is no record then ##RowCount would be 0.
Based on that Insert it as a new record.
*/
CREATE PROCEDURE uspUPSert_Ver2
(
#empID INT,
#fname VARCHAR(25),
#lname VARCHAR(25),
#emailid VARCHAR(50)
)
AS
BEGIN
SET NOCOUNT ON
BEGIN TRAN
UPDATE tblUpsert WITH (SERIALIZABLE)
SET emailid = #emailid ,
firstname = #fname ,
lastname = #lname
WHERE EmpID = #empID
IF ##ROWCOUNT = 0
BEGIN
INSERT INTO tblUpsert VALUES (#empID, #fname, #lname, #emailid)
END
COMMIT TRAN
END
GO
seems like you would need either a primary key or a unique constraint on the columns that identify the rows as duplicate. Then if there is an error in the insert that violates the unique constraint the row won't insert. Catch the exception, log it to a different table for future validation and move to the next row.
http://www.w3schools.com/sql/sql_unique.asp

asp calendar 0001/01/01

I have a calendar in an aspx page, if the user doesn't select a date it puts 0001/01/01 into the database. How can I specify another date, like put today's date instead if no date is chosen?
There are couple of ways. If it is the Calendar control, you can programatically set the selected date on Page_Load to Today's date. That way even if the user doesn't select a date, you get the default selected date.
Second option would be, before inserting to the database - you can check if the selected date is <=DateTime.MinDate, and set current date in the object.
You could replace the "0001/01/01" with convert(varchar(10),getdate(),101)
There are two ways:
1) If the date field is empty then assign the date field value as system.datetime.now
so that while you are passing it to the procedure you can insert the current date.
for example txtdate is field where date is assigned
if(txtdate.text == "")
{
txtdate.text = system.datetime.now;
}
pass this to the procedure.
2)in the database level,check whether the date is empty or not
If it is empty then assign date as getdate()
for example
create procedure test(#date varchar(50) = '')
as
begin
if(#date <> '')
begin
-- your code goes here
end
else if(#date = '')
begin
getdate() value to #date
end

Categories

Resources