Skip to content
GitLab
Explore
Projects
Groups
Topics
Snippets
Projects
Groups
Topics
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Register
Sign in
Toggle navigation
Menu
UPSMF
user-service
Commits
ee38540d
Unverified
Commit
ee38540d
authored
2 years ago
by
Abhishek Mishra
Committed by
GitHub
2 years ago
Browse files
Options
Download
Plain Diff
Merge pull request #49 from choxx/reset-password-generic-apis
Password reset APIs (OTP based)
parents
0153d1d5
1faa69b1
master
v2.4.4
v2.4.3
v2.4.2
v2.4.1
v2.4.0
v2.3.9
v2.3.8
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/api/api.controller.ts
+27
-0
src/api/api.controller.ts
src/api/api.service.ts
+101
-1
src/api/api.service.ts
src/api/fusionauth/fusionauth.service.ts
+48
-271
src/api/fusionauth/fusionauth.service.ts
with
176 additions
and
272 deletions
+176
-272
src/api/api.controller.ts
+
27
−
0
View file @
ee38540d
...
...
@@ -20,6 +20,7 @@ import { FusionauthService } from './fusionauth/fusionauth.service';
import
{
OtpService
}
from
'
./otp/otp.service
'
;
import
{
SMSResponse
}
from
'
./sms/sms.interface
'
;
import
{
RefreshRequest
}
from
'
@fusionauth/typescript-client/build/src/FusionAuthClient
'
;
import
{
ChangePasswordDTO
}
from
'
../user/dto/changePassword.dto
'
;
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
CryptoJS
=
require
(
'
crypto-js
'
);
...
...
@@ -266,4 +267,30 @@ export class ApiController {
authHeader
,
);
}
@
Post
(
'
/changePassword/sendOTP
'
)
async
changePasswordOTP
(
@
Headers
(
'
authorization
'
)
authHeader
,
@
Headers
(
'
x-application-id
'
)
applicationId
,
@
Body
()
data
:
any
,
):
Promise
<
SignupResponse
>
{
return
await
this
.
apiService
.
changePasswordOTP
(
data
.
username
,
applicationId
,
authHeader
,
);
}
@
Patch
(
'
/changePassword/update
'
)
async
changePassword
(
@
Headers
(
'
authorization
'
)
authHeader
,
@
Headers
(
'
x-application-id
'
)
applicationId
,
@
Body
()
data
:
ChangePasswordDTO
,
):
Promise
<
SignupResponse
>
{
return
await
this
.
apiService
.
changePassword
(
data
,
applicationId
,
authHeader
,
);
}
}
This diff is collapsed.
Click to expand it.
src/api/api.service.ts
+
101
−
1
View file @
ee38540d
...
...
@@ -20,6 +20,9 @@ import { OtpService } from './otp/otp.service';
import
{
v4
as
uuidv4
}
from
'
uuid
'
;
import
{
ConfigResolverService
}
from
'
./config.resolver.service
'
;
import
{
RefreshRequest
}
from
'
@fusionauth/typescript-client/build/src/FusionAuthClient
'
;
import
{
FAStatus
}
from
'
../user/fusionauth/fusionauth.service
'
;
import
{
ChangePasswordDTO
}
from
'
../user/dto/changePassword.dto
'
;
import
{
SMSResponseStatus
}
from
'
../user/sms/sms.interface
'
;
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
CryptoJS
=
require
(
'
crypto-js
'
);
// eslint-disable-next-line @typescript-eslint/no-var-requires
...
...
@@ -214,7 +217,7 @@ export class ApiService {
applicationId
:
string
,
authHeader
?:
string
,
):
Promise
<
any
>
{
return
this
.
fusionAuthService
.
upd
d
atePasswordWithLoginId
(
return
this
.
fusionAuthService
.
updatePasswordWithLoginId
(
data
,
applicationId
,
authHeader
,
...
...
@@ -408,4 +411,101 @@ export class ApiService {
response
.
result
=
userResponse
.
user
;
return
response
;
}
async
changePasswordOTP
(
username
:
string
,
applicationId
:
UUID
,
authHeader
:
null
|
string
,
):
Promise
<
SignupResponse
>
{
// Get Phone No from username
const
{
statusFA
,
userId
,
user
,
}:
{
statusFA
:
FAStatus
;
userId
:
UUID
;
user
:
User
}
=
await
this
.
fusionAuthService
.
getUser
(
username
,
applicationId
,
authHeader
);
const
response
:
SignupResponse
=
new
SignupResponse
().
init
(
uuidv4
());
// If phone number is valid => Send OTP
if
(
statusFA
===
FAStatus
.
USER_EXISTS
)
{
const
re
=
/^
[
6-9
]{1}[
0-9
]{9}
$/
;
if
(
re
.
test
(
user
.
mobilePhone
))
{
const
result
=
await
this
.
otpService
.
sendOTP
(
user
.
mobilePhone
);
response
.
result
=
{
data
:
result
,
responseMsg
:
`OTP has been sent to
${
user
.
mobilePhone
}
.`
,
};
response
.
responseCode
=
ResponseCode
.
OK
;
response
.
params
.
status
=
ResponseStatus
.
success
;
}
else
{
response
.
responseCode
=
ResponseCode
.
FAILURE
;
response
.
params
.
err
=
'
INVALID_PHONE_NUMBER
'
;
response
.
params
.
errMsg
=
'
Invalid Phone number
'
;
response
.
params
.
status
=
ResponseStatus
.
failure
;
}
}
else
{
response
.
responseCode
=
ResponseCode
.
FAILURE
;
response
.
params
.
err
=
'
INVALID_USERNAME
'
;
response
.
params
.
errMsg
=
'
No user with this Username exists
'
;
response
.
params
.
status
=
ResponseStatus
.
failure
;
}
return
response
;
}
async
changePassword
(
data
:
ChangePasswordDTO
,
applicationId
:
UUID
,
authHeader
:
null
|
string
,
):
Promise
<
SignupResponse
>
{
// Verify OTP
const
{
statusFA
,
userId
,
user
,
}:
{
statusFA
:
FAStatus
;
userId
:
UUID
;
user
:
User
}
=
await
this
.
fusionAuthService
.
getUser
(
data
.
username
,
applicationId
,
authHeader
,
);
const
response
:
SignupResponse
=
new
SignupResponse
().
init
(
uuidv4
());
if
(
statusFA
===
FAStatus
.
USER_EXISTS
)
{
const
verifyOTPResult
=
await
this
.
otpService
.
verifyOTP
({
phone
:
user
.
mobilePhone
,
otp
:
data
.
OTP
,
});
if
(
verifyOTPResult
.
status
===
SMSResponseStatus
.
success
)
{
const
result
=
await
this
.
fusionAuthService
.
updatePassword
(
userId
,
data
.
password
,
applicationId
,
authHeader
,
);
if
(
result
.
statusFA
==
FAStatus
.
SUCCESS
)
{
response
.
result
=
{
responseMsg
:
'
Password updated successfully
'
,
};
response
.
responseCode
=
ResponseCode
.
OK
;
response
.
params
.
status
=
ResponseStatus
.
success
;
}
else
{
response
.
responseCode
=
ResponseCode
.
FAILURE
;
response
.
params
.
err
=
'
UNCAUGHT_EXCEPTION
'
;
response
.
params
.
errMsg
=
'
Server Error
'
;
response
.
params
.
status
=
ResponseStatus
.
failure
;
}
}
else
{
response
.
responseCode
=
ResponseCode
.
FAILURE
;
response
.
params
.
err
=
'
INVALID_OTP_USERNAME_PAIR
'
;
response
.
params
.
errMsg
=
'
OTP and Username did not match.
'
;
response
.
params
.
status
=
ResponseStatus
.
failure
;
}
}
else
{
response
.
responseCode
=
ResponseCode
.
FAILURE
;
response
.
params
.
err
=
'
INVALID_USERNAME
'
;
response
.
params
.
errMsg
=
'
No user with this Username exists
'
;
response
.
params
.
status
=
ResponseStatus
.
failure
;
}
return
response
;
}
}
This diff is collapsed.
Click to expand it.
src/api/fusionauth/fusionauth.service.ts
+
48
−
271
View file @
ee38540d
...
...
@@ -3,12 +3,10 @@ import FusionAuthClient, {
LoginResponse
,
RegistrationRequest
,
RegistrationResponse
,
SearchRequest
,
SearchResponse
,
Sort
,
UUID
,
User
,
UserRegistration
,
UserRequest
,
UserResponse
,
Error
,
...
...
@@ -50,10 +48,29 @@ export class FusionauthService {
return
new
FusionAuthClient
(
apiKey
,
host
);
}
/**
* Returns the FA client for the given applicationId &/or authHeader
* @param applicationId
* @param authHeader
*/
getClientForApplicationId
(
applicationId
:
UUID
,
authHeader
:
null
|
string
,
):
FusionAuthClient
{
let
apiKey
=
this
.
configResolverService
.
getApiKey
(
applicationId
);
if
(
authHeader
!=
null
)
{
apiKey
=
authHeader
;
}
const
host
=
this
.
configResolverService
.
getHost
(
applicationId
);
return
this
.
getClient
(
apiKey
,
host
);
}
getUser
(
username
:
string
,
applicationId
:
UUID
,
authHeader
:
null
|
string
,
):
Promise
<
{
statusFA
:
FAStatus
;
userId
:
UUID
;
user
:
User
}
>
{
return
this
.
fusionauthClient
return
this
.
getClientForApplicationId
(
applicationId
,
authHeader
)
.
retrieveUserByUsername
(
username
)
.
then
(
(
...
...
@@ -183,145 +200,6 @@ export class FusionauthService {
});
}
updatePasswordWithUserId
(
userId
:
UUID
,
password
:
string
,
):
Promise
<
{
statusFA
:
FAStatus
;
userId
:
UUID
}
>
{
return
this
.
fusionauthClient
.
patchUser
(
userId
,
{
user
:
{
password
:
password
,
},
})
.
then
((
response
)
=>
{
return
{
statusFA
:
FAStatus
.
SUCCESS
,
userId
:
response
.
response
.
user
.
id
,
};
})
.
catch
((
response
)
=>
{
console
.
log
(
JSON
.
stringify
(
response
));
return
{
statusFA
:
FAStatus
.
ERROR
,
userId
:
null
,
};
});
}
delete
(
userId
:
UUID
):
Promise
<
any
>
{
return
this
.
fusionauthClient
.
deleteUser
(
userId
)
.
then
((
response
)
=>
{
console
.
log
(
response
);
})
.
catch
((
e
)
=>
{
console
.
log
(
e
);
});
}
persist
(
authObj
:
any
):
Promise
<
{
statusFA
:
FAStatus
;
userId
:
UUID
}
>
{
console
.
log
(
authObj
);
let
resp
;
const
registrations
:
Array
<
UserRegistration
>
=
[];
const
currentRegistration
:
UserRegistration
=
{
username
:
authObj
.
username
,
applicationId
:
process
.
env
.
FUSIONAUTH_APPLICATION_ID
,
roles
:
authObj
.
role
,
};
const
currentRegistration_samarth_hp
:
UserRegistration
=
{
username
:
authObj
.
username
,
applicationId
:
process
.
env
.
FUSIONAUTH_SAMARTH_HP_APPLICATION_ID
,
roles
:
authObj
.
role
,
};
registrations
.
push
(
currentRegistration
);
const
userRequest
:
RegistrationRequest
=
{
user
:
{
active
:
true
,
data
:
{
school
:
authObj
.
school
,
education
:
authObj
.
education
,
address
:
authObj
.
address
,
gender
:
authObj
.
gender
,
dateOfRetirement
:
authObj
.
dateOfRetirement
,
phoneVerified
:
false
,
udise
:
authObj
.
udise
,
},
email
:
authObj
.
email
,
firstName
:
authObj
.
firstName
,
lastName
:
authObj
.
lastName
,
username
:
authObj
.
username
,
password
:
authObj
.
password
,
imageUrl
:
authObj
.
avatar
,
mobilePhone
:
authObj
.
phone
,
},
registration
:
currentRegistration
,
};
const
userRequest_samarth_hp
:
RegistrationRequest
=
{
registration
:
currentRegistration_samarth_hp
,
};
// eslint-disable-next-line prefer-const
resp
=
this
.
fusionauthClient
.
register
(
undefined
,
userRequest
)
.
then
(
(
response
:
ClientResponse
<
RegistrationResponse
>
,
):
{
statusFA
:
FAStatus
;
userId
:
UUID
}
=>
{
this
.
fusionauthClient
.
register
(
response
.
response
.
user
.
id
,
userRequest_samarth_hp
)
.
then
((
res
:
ClientResponse
<
RegistrationResponse
>
):
any
=>
{
console
.
log
({
res
});
})
.
catch
((
e
):
Promise
<
{
statusFA
:
FAStatus
;
userId
:
UUID
}
>
=>
{
console
.
log
(
'
Could not create a user in
'
,
JSON
.
stringify
(
e
));
console
.
log
(
'
Trying to fetch an existing user in
'
);
return
this
.
fusionauthClient
.
retrieveUserByUsername
(
authObj
.
username
)
.
then
((
response
:
ClientResponse
<
UserResponse
>
):
any
=>
{
console
.
log
(
'
Found user in
'
);
})
.
catch
((
e
):
any
=>
{
console
.
log
(
`Could not fetch user with username in
${
authObj
.
username
}
`
,
JSON
.
stringify
(
e
),
);
});
});
return
{
statusFA
:
FAStatus
.
SUCCESS
,
userId
:
response
.
response
.
user
.
id
,
};
},
)
.
catch
((
e
):
Promise
<
{
statusFA
:
FAStatus
;
userId
:
UUID
}
>
=>
{
console
.
log
(
'
Could not create a user
'
,
JSON
.
stringify
(
e
));
console
.
log
(
'
Trying to fetch an existing user
'
);
return
this
.
fusionauthClient
.
retrieveUserByUsername
(
authObj
.
username
)
.
then
(
(
response
:
ClientResponse
<
UserResponse
>
,
):
{
statusFA
:
FAStatus
;
userId
:
UUID
}
=>
{
console
.
log
(
'
Found user
'
);
return
{
statusFA
:
FAStatus
.
USER_EXISTS
,
userId
:
response
.
response
.
user
.
id
,
};
},
)
.
catch
((
e
):
{
statusFA
:
FAStatus
;
userId
:
UUID
}
=>
{
console
.
log
(
`Could not fetch user with username
${
authObj
.
username
}
`
,
JSON
.
stringify
(
e
),
);
return
{
statusFA
:
FAStatus
.
ERROR
,
userId
:
null
,
};
});
});
return
resp
;
}
login
(
user
:
LoginRequest
,
authHeader
:
string
,
...
...
@@ -345,134 +223,6 @@ export class FusionauthService {
});
}
update
(
userID
:
UUID
,
authObj
:
any
,
isSimpleUpdate
=
false
,
):
Promise
<
{
statusFA
:
FAStatus
;
userId
:
UUID
;
fusionAuthUser
:
User
}
>
{
let
userRequest
:
UserRequest
;
if
(
!
isSimpleUpdate
)
{
const
registrations
:
Array
<
UserRegistration
>
=
[];
const
currentRegistration
:
UserRegistration
=
{
username
:
authObj
.
username
,
applicationId
:
process
.
env
.
FUSIONAUTH_APPLICATION_ID
,
roles
:
authObj
.
role
,
};
registrations
.
push
(
currentRegistration
);
userRequest
=
{
user
:
{
active
:
true
,
data
:
{
school
:
authObj
.
school
,
education
:
authObj
.
education
,
address
:
authObj
.
address
,
gender
:
authObj
.
gender
,
dateOfRetirement
:
authObj
.
dateOfRetirement
,
phoneVerified
:
false
,
udise
:
authObj
.
udise
,
phone
:
authObj
.
phone
,
accountName
:
authObj
.
firstName
,
},
email
:
authObj
.
email
,
firstName
:
authObj
.
firstName
,
lastName
:
authObj
.
lastName
,
fullName
:
authObj
.
fullName
,
username
:
authObj
.
username
,
password
:
authObj
.
password
,
imageUrl
:
authObj
.
avatar
,
mobilePhone
:
authObj
.
phone
,
},
};
}
else
{
userRequest
=
{
user
:
authObj
,
};
}
return
this
.
fusionauthClient
.
patchUser
(
userID
,
userRequest
)
.
then
(
(
response
:
ClientResponse
<
UserResponse
>
,
):
{
statusFA
:
FAStatus
;
userId
:
UUID
;
fusionAuthUser
:
User
}
=>
{
console
.
log
({
response
});
return
{
statusFA
:
FAStatus
.
SUCCESS
,
userId
:
response
.
response
.
user
.
id
,
fusionAuthUser
:
response
.
response
.
user
,
};
},
)
.
catch
(
(
e
):
{
statusFA
:
FAStatus
;
userId
:
UUID
;
fusionAuthUser
:
User
}
=>
{
console
.
log
(
'
Unable to update user
'
,
JSON
.
stringify
(
e
));
return
{
statusFA
:
FAStatus
.
ERROR
,
userId
:
null
,
fusionAuthUser
:
null
,
};
},
);
}
verifyUsernamePhoneCombination
():
Promise
<
boolean
>
{
return
Promise
.
resolve
(
true
);
}
//One time Task
async
updateAllEmptyRolesToSchool
():
Promise
<
any
>
{
let
allDone
=
false
;
const
searchRequest
:
SearchRequest
=
{
search
:
{
numberOfResults
:
15
,
startRow
:
0
,
sortFields
:
[
{
missing
:
'
_first
'
,
name
:
'
id
'
,
order
:
Sort
.
asc
,
},
],
query
:
'
{"bool":{"must":[{"nested":{"path":"registrations","query":{"bool":{"must":[{"match":{"registrations.applicationId":"f0ddb3f6-091b-45e4-8c0f-889f89d4f5da"}}],"must_not":[{"match":{"registrations.roles":"school"}}]}}}}]}}
'
,
},
};
let
iteration
=
0
;
let
invalidUsersCount
=
0
;
while
(
!
allDone
)
{
iteration
+=
1
;
searchRequest
.
search
.
startRow
=
invalidUsersCount
;
const
resp
:
ClientResponse
<
SearchResponse
>
=
await
this
.
fusionauthClient
.
searchUsersByQuery
(
searchRequest
);
const
total
=
resp
.
response
.
total
;
console
.
log
(
iteration
,
total
);
if
(
total
===
0
)
allDone
=
true
;
else
{
const
users
:
Array
<
User
>
=
resp
.
response
.
users
;
for
(
const
user
of
users
)
{
if
(
user
.
registrations
[
0
].
roles
===
undefined
)
{
user
.
registrations
[
0
].
roles
=
[
'
school
'
];
console
.
log
(
'
Here
'
,
user
);
await
this
.
fusionauthClient
.
updateRegistration
(
user
.
id
,
{
registration
:
user
.
registrations
[
0
],
})
.
then
((
resp
)
=>
{
console
.
log
(
'
response
'
,
JSON
.
stringify
(
resp
));
})
.
catch
((
e
)
=>
{
console
.
log
(
'
error
'
,
JSON
.
stringify
(
e
));
});
}
else
{
console
.
log
(
'
Invalid User
'
,
user
.
id
);
invalidUsersCount
+=
1
;
}
}
}
}
}
async
createAndRegisterUser
(
user
:
RegistrationRequest
,
applicationId
:
string
,
...
...
@@ -544,7 +294,7 @@ export class FusionauthService {
});
}
async
upd
d
atePasswordWithLoginId
(
async
updatePasswordWithLoginId
(
data
:
{
loginId
:
string
;
password
:
string
},
applicationId
:
string
,
authHeader
?:
string
,
...
...
@@ -735,4 +485,31 @@ export class FusionauthService {
};
});
}
updatePassword
(
userId
:
UUID
,
password
:
string
,
applicationId
,
authHeader
?:
null
|
string
,
):
Promise
<
{
statusFA
:
FAStatus
;
userId
:
UUID
}
>
{
return
this
.
getClientForApplicationId
(
applicationId
,
authHeader
)
.
patchUser
(
userId
,
{
user
:
{
password
:
password
,
},
})
.
then
((
response
)
=>
{
return
{
statusFA
:
FAStatus
.
SUCCESS
,
userId
:
response
.
response
.
user
.
id
,
};
})
.
catch
((
response
)
=>
{
console
.
log
(
JSON
.
stringify
(
response
));
return
{
statusFA
:
FAStatus
.
ERROR
,
userId
:
null
,
};
});
}
}
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment
Menu
Explore
Projects
Groups
Topics
Snippets