diff --git a/.github/workflows/chart-lint-publish.yml b/.github/workflows/chart-lint-publish.yml
index df1158d8..8acf19a4 100644
--- a/.github/workflows/chart-lint-publish.yml
+++ b/.github/workflows/chart-lint-publish.yml
@@ -6,7 +6,7 @@ on:
pull_request:
types: [opened, reopened, synchronize]
paths:
- - 'charts/**'
+ - 'helm/**'
workflow_dispatch:
inputs:
IGNORE_CHARTS:
@@ -41,7 +41,7 @@ on:
- release*
- ES-*
paths:
- - 'charts/**'
+ - 'helm/**'
jobs:
chart-lint-publish:
diff --git a/.github/workflows/push-trigger.yml b/.github/workflows/push-trigger.yml
index 9aadb84d..573dcd77 100644
--- a/.github/workflows/push-trigger.yml
+++ b/.github/workflows/push-trigger.yml
@@ -38,6 +38,7 @@ jobs:
sonar_analysis:
needs: build-maven-signup-service
+ if: "${{ github.event_name != 'pull_request' }}"
uses: mosip/kattu/.github/workflows/maven-sonar-analysis.yml@master
with:
SERVICE_LOCATION: 'signup-service'
diff --git a/Credits.md b/Credits.md
new file mode 100644
index 00000000..e589f9df
--- /dev/null
+++ b/Credits.md
@@ -0,0 +1,12 @@
+# Credits
+
+This project is made possible by the people and organizations listed in this document.
+
+## Contributors
+
+* Rathanak SREANG (rathanak-0080)
+* Panharith AN (panharith-0118)
+* Bunsy Chhay (bunsy-0900)
+* Mengleang Ngoun (mengleang-0090)
+* Oeun Lengheang (lengheang-0116)
+* Un Lykong (unlykong)
diff --git a/README.md b/README.md
index 9cafdd76..eca72f2f 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,61 @@
signup-service is part of the esignet modules, but has a separate Helm chart so as to install and manage it in a completely independent namespace.
+Below diagram depicts the high level deployment architecture for signup service with MOSIP ID-repo.
+
+![](docs/signup-with-mosip-id-repo.png)
+
+### Configurations
+Signup service and signup UI currently supports default [ID schema](docs/id-schema.json) only.
+
+**Note:**
+Work is in progress to support any ID schema and also to connect with any registry services.
+
+With respect to the default ID schema, below MOSIP configurations are required to be updated.
+
+#### admin-default.properties
+``
+mosip.admin.masterdata.lang-code=eng,khm
+``
+
+#### application-default.properties
+```
+mosip.mandatory-languages=eng,khm
+
+mosip.optional-languages=
+
+mosip.default.template-languages=eng,khm
+```
+
+#### id-authentication-default.properties
+```
+request.idtypes.allowed=UIN,HANDLE
+
+request.idtypes.allowed.internalauth=UIN
+
+ida.mosip.external.auth.filter.classes.in.execution.order=io.mosip.authentication.hotlistfilter.impl.PartnerIdHotlistFilterImpl,io.mosip.authentication.hotlistfilter.impl.IndividualIdHotlistFilterImpl,io.mosip.authentication.hotlistfilter.impl.DeviceProviderHotlistFilterImpl,io.mosip.authentication.hotlistfilter.impl.DeviceHotlistFilterImpl,io.mosip.authentication.authtypelockfilter.impl.AuthTypeLockFilterImpl
+
+mosip.ida.handle-types.regex={ '@phone' : '^\\+91[1-9][0-9]{7,9}@phone$' }
+```
+
+#### id-repository-default.properties
+```
+mosip.idrepo.credential.request.enable-convention-based-id=true
+
+mosip.idrepo.identity.disable-uin-based-credential-request=false
+
+mosip.idrepo.vid.disable-support=true
+
+mosip.identity.fieldid.handle-postfix.mapping={'phone':'@phone'}
+```
+
+#### kernel-default.properties
+``
+mosip.kernel.sms.country.code=+91
+``
+
+
+
## Installing in k8s cluster using helm
### Pre-requisites
1. Set the kube config file of the Mosip cluster having dependent services is set correctly in PC.
@@ -53,9 +108,15 @@ signup-service is part of the esignet modules, but has a separate Helm chart so
cd helm
./restart-all.sh
```
+
## APIs
-API documentation is available [here](https://mosip.stoplight.io/docs/identity-provider/branches/signupV1/t9tvfbteqqokf-e-signet-signup-portal-ap-is).
+API documentation is available [here](docs/esignet-signup-openapi.yaml).
+
+## Credits
+
+We extend our sincere appreciation to the [Cambodia Digital Government Committee team](/Credits.md) for their invaluable support to MOSIP by implementing the Signup UI and service module. We are truly impressed by your commitment and outstanding contribution.
+
## License
This project is licensed under the terms of [Mozilla Public License 2.0](LICENSE).
diff --git a/docs/esignet-signup-openapi.yaml b/docs/esignet-signup-openapi.yaml
new file mode 100644
index 00000000..478f7f3f
--- /dev/null
+++ b/docs/esignet-signup-openapi.yaml
@@ -0,0 +1,749 @@
+openapi: 3.1.0
+info:
+ version: '1.0'
+ title: e-Signet Signup Portal APIs
+ summary: Signup portal for e-Signet one-login system.
+ description: Signup portal for e-Signet one-login system.
+ contact:
+ name: MOSIP Team
+ email: info@mosip.io
+ url: 'https://www.mosip.io/'
+ license:
+ url: 'https://www.mozilla.org/en-US/MPL/2.0/'
+ name: MPL-2.0
+servers:
+ - url: 'https://signup.collab.mosip.net/v1/signup'
+paths:
+ /settings:
+ get:
+ tags:
+ - UI
+ summary: UI Settings Endpoint
+ description: |-
+ Endpoint to get the configurations required by the signup UI.
+
+ All these UI configurations should be taken from the configurations.
+ operationId: get-details
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ responseTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ response:
+ type: object
+ properties:
+ configs:
+ $ref: '#/components/schemas/UIConfigMap'
+ description: Its key-value pairs of ui configuration.
+ errors:
+ type:
+ - array
+ - 'null'
+ description: List of errors in case of request validation / processing failure in the server.
+ items:
+ type: object
+ properties:
+ errorCode:
+ type: string
+ enum:
+ - invalid_transaction
+ - unknown_error
+ errorMessage:
+ type: string
+ enum:
+ - invalid_transaction
+ - unknown_error
+ examples:
+ Example 1:
+ value:
+ responseTime: '2011-10-05T14:48:00.000Z'
+ response:
+ configs:
+ identifier.pattern: '^\\+855[1-9]\\d{7,8}$'
+ identifier.prefix: '+855'
+ captcha.site.key: 6LeFAAAAAMaOuSNQxj3VDbERZcyc_1UO_9xT
+ otp.length: 6
+ otp.secret: true
+ password.pattern: '^(?\u003d.*[0-9])(?\u003d.{8,20})[a-zA-Z0-9\\x5F\\W]{8,20}$'
+ challenge.timeout: 30
+ resend.attempts: 4
+ resend.delay: 30
+ fullname.pattern: '^[\\u1780-\\u17FF\\u19E0-\\u19FF\\u1A00-\\u1A9F\\u0020]{1,30}$'
+ status.request.delay: 20
+ status.request.limit: 10
+ popup.timeout: 50
+ identifier.allowed.characters: '^[0-9]+'
+ identifier.length.min: 8
+ identifier.length.max: 9
+ fullname.allowed.characters: '^[\\u1780-\\u17FF\\u19E0-\\u19FF\\u1A00-\\u1A9F\\u0020]'
+ fullname.length.min: 1
+ fullname.length.max: 30
+ otp.blocked: 120
+ errors:
+ - errorCode: invalid_transaction
+ errorMessage: invalid_transaction
+ servers:
+ - url: 'https://signup.collab.mosip.net/v1/signup'
+ /registration/generate-challenge:
+ post:
+ tags:
+ - UI
+ summary: Generate Challenge Endpoint
+ description: |-
+ Endpoint to generate challenge for the input identifier of the user.
+ For eg: if the provided identifier is phone number, OTP is sent to phone. If the identifier is email, OTP is mailed to the given emailID.
+
+ TransactionId is created and stored in the cache to maintain the state of the challenge specific to input user identifier.
+
+ 1. Should identify if the provided identifier is phone number or emailID.
+ 2. Response header should set-cookie with transactionId
+ 3. On success, return status as SUCCESS
+ 4. In Failure, response is set to null, errors list if set with specific errorCode.
+ 5. if regenerate is true, then a valid transactionId is excepted in the cookie to re-generate the challenge in the existing transaction.
+ 6. Purpose of the challenge is set on starting of new transaction. Challenge generated for "Registration" should be used only for registration process.
+ And challenge generated for RESET_PASSWORD should be used only to reset password.
+ operationId: post-send-otp
+ parameters:
+ - name: X-XSRF-TOKEN
+ in: header
+ description: CSRF token as set in cookie key 'XSRF-TOKEN'
+ required: true
+ schema:
+ type: string
+ requestBody:
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ requestTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ request:
+ type: object
+ properties:
+ identifier:
+ type: string
+ description: A unique Identifier against which a challange can be generated for verification. Ex. Phonenumber
+ captchaToken:
+ type: string
+ description: 'Captcha token, if enabled.'
+ locale:
+ type: string
+ description: |-
+ Locale to be used to send the challege in the notification to the user.
+ If not provided default notification language is considered.
+ regenerate:
+ type: boolean
+ description: |-
+ True - when we should resend the challenge for existing transaction.
+ False - when a new transaction has to be started.
+ Default value is False.
+ purpose:
+ type: string
+ enum:
+ - REGISTRATION
+ - RESET_PASSWORD
+ description: Marks the purpose of this challenge in the transaction.
+ required:
+ - identifier
+ - captchaToken
+ - purpose
+ required:
+ - requestTime
+ - request
+ examples:
+ Example 1:
+ value:
+ requestTime: '2011-10-05T14:48:00.000Z'
+ request:
+ identifier: +8557357xxxxx
+ captchaToken: asdncjdnsdchd
+ locale: eng
+ regenerate: true
+ purpose: REGISTRATION
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ responseTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ response:
+ type: object
+ description: 'If successful otp details, or null if failed to deliver OTP.'
+ properties:
+ status:
+ const: SUCCESS
+ description: Status of challenge verification.
+ errors:
+ type: array
+ description: List of Errors in case of request validation / processing failure in the server.
+ items:
+ type: object
+ properties:
+ errorCode:
+ type: string
+ enum:
+ - invalid_transaction
+ - invalid_otp_channel
+ - invalid_captcha
+ - send_otp_failed
+ - active_otp_found
+ - unknown_error
+ errorMessage:
+ type: string
+ enum:
+ - invalid_transaction
+ - invalid_otp_channel
+ - invalid_captcha
+ - send_otp_failed
+ - active_otp_found
+ - unknown_error
+ examples:
+ Example 1:
+ value:
+ responseTime: '2023-11-03T11:03:30.000Z'
+ response:
+ status: SUCCESS
+ errors: []
+ headers:
+ set-cookie:
+ schema:
+ type: string
+ example: 'Set-Cookie: TRANSACTION_ID=2GFKHGAEyyx6lEhB4ObBzpPuaTrTlKy3BK0Izl3taug; Max-Age=600; Secure; HttpOnly'
+ description: Transaction Id is set in the cookie
+ servers:
+ - url: 'https://signup.collab.mosip.net/v1/signup'
+ /registration/verify-challenge:
+ post:
+ tags:
+ - UI
+ summary: Challenge Verification Endpoint
+ description: |-
+ Endpoint to verify with the provided challenge w.r.t the transaction ID.
+
+ 1. TransactionId from the cookie is validated.
+ 2. validate the challenge.
+ 3. identifier in the request MUST match the identifier stored in the cache.
+ 3. On success, return status as SUCCESS
+ 4. In Failure, response is set to null, errors list if set with specific errorCode.
+
+ TransactionId and setting the same in the new cookie, post successful challenge verification.
+ Old cookie is removed by setting age to 0.
+ operationId: post-verify-challenge
+ parameters:
+ - name: X-XSRF-TOKEN
+ in: header
+ description: CSRF token as set in cookie key 'XSRF-TOKEN'
+ required: true
+ schema:
+ type: string
+ - name: TRANSACTION_ID
+ in: cookie
+ description: Transaction Id set after successful generate-challenge response
+ required: true
+ schema:
+ type: string
+ requestBody:
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ requestTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ request:
+ type: object
+ properties:
+ identifier:
+ type: string
+ description: A unique Identifier against which a challange can be generated for verification. Ex. Phonenumber
+ challengeInfo:
+ type: array
+ description: List of Challenges generated
+ items:
+ $ref: '#/components/schemas/ChallengeInfo'
+ required:
+ - identifier
+ - challengeInfo
+ required:
+ - requestTime
+ - request
+ examples:
+ Example 1:
+ value:
+ requestTime: '2011-10-05T14:48:00.000Z'
+ request:
+ identifier: string
+ challengeInfo:
+ - challenge: string
+ format: alpha-numeric
+ type: OTP
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ responseTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ response:
+ type: object
+ properties:
+ status:
+ const: SUCCESS
+ description: Status of challenge verification.
+ errors:
+ type: array
+ description: List of Errors in case of request validation / processing failure in Idp server.
+ items:
+ type: object
+ properties:
+ errorCode:
+ type: string
+ enum:
+ - invalid_transaction
+ - challenge_failed
+ - invalid_challenge_type
+ - invalid_challenge_format
+ - unknown_error
+ - already-registered
+ errorMessage:
+ type: string
+ enum:
+ - invalid_transaction
+ - challenge_failed
+ - invalid_challenge_type
+ - invalid_challenge_format
+ - unknown_error
+ - already-registered
+ examples:
+ Example 1:
+ value:
+ responseTime: '2023-11-03T11:03:49.770Z'
+ response:
+ status: SUCCESS
+ errors: []
+ headers:
+ set-cookie:
+ schema:
+ type: string
+ description: Verified transaction Id to be set after successful challenge verification
+ servers:
+ - url: 'https://signup.collab.mosip.net/v1/signup'
+ /registration/register:
+ post:
+ tags:
+ - UI
+ summary: Register Endpoint
+ description: |-
+ Endpoint to register the individual.
+
+ 1. username is with country code including + symbol if present.
+ 2. if username is phone number, the same should be set as value to "phone" field.
+ 3. Fields with no value should be set to null in userInfo.
+
+ Note: We should clearly convey that username contains country code in the UI after registration.
+ operationId: post-register
+ parameters:
+ - name: X-XSRF-TOKEN
+ in: header
+ description: CSRF token as set in cookie key 'XSRF-TOKEN'
+ required: true
+ schema:
+ type: string
+ - name: VERIFIED_TRANSACTION_ID
+ in: cookie
+ description: Transaction Id set after successful verify-challenge response
+ required: true
+ schema:
+ type: string
+ requestBody:
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ requestTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ request:
+ type: object
+ properties:
+ username:
+ type: string
+ description: Unique identifier to be registered.
+ password:
+ type: string
+ description: Password associated with the username
+ consent:
+ type: string
+ description: Consent to store the user info.
+ userInfo:
+ $ref: '#/components/schemas/UserInfoMap'
+ description: 'This is a map, every key-value here is a field published in the identity-schema.'
+ required:
+ - username
+ - password
+ - consent
+ - userInfo
+ required:
+ - requestTime
+ - request
+ examples:
+ Example 1:
+ value:
+ requestTime: '2023-11-03T11:03:49.770Z'
+ request:
+ username: '85534567890'
+ password:
+ consent: AGREE
+ userInfo:
+ fullName:
+ - language: khm
+ value: អានុសា
+ phone: '+85534567890'
+ preferredLang: eng
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ responseTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ response:
+ type: object
+ properties:
+ status:
+ type: string
+ enum:
+ - PENDING
+ - COMPLETED
+ description: Status of registration
+ errors:
+ type: array
+ description: List of Errors in case of request validation / processing failure in the server.
+ items:
+ type: object
+ properties:
+ errorCode:
+ type: string
+ enum:
+ - invalid_transaction
+ - unknown_error
+ errorMessage:
+ type: string
+ enum:
+ - invalid_transaction
+ - unknown_error
+ examples:
+ Example 1:
+ value:
+ responseTime: '2023-11-03T11:03:49.770Z'
+ response:
+ status: PENDING
+ errors: []
+ servers:
+ - url: 'https://signup.collab.mosip.net/v1/signup'
+ /registration/status:
+ get:
+ tags:
+ - UI
+ summary: Registration Status Endpoint
+ description: |-
+ Endpoint to get the latest registration/reset-password status.
+
+ 1. validate the verified_transaction id in the cookie.
+ 2. check status of each handle registered.
+ 3. Once the status of all the registered handles are in end statuses (Completed / Failed). Mark the
+ transaction as completed.
+ 4. Return back the final status in the response.
+ operationId: get-registration-status
+ parameters:
+ - name: X-XSRF-TOKEN
+ in: header
+ description: CSRF token as set in cookie key 'XSRF-TOKEN'
+ required: true
+ schema:
+ type: string
+ - name: VERIFIED_TRANSACTION_ID
+ in: cookie
+ description: Transaction Id set after successful verify-challenge response
+ required: true
+ schema:
+ type: string
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ responseTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ response:
+ type: object
+ properties:
+ status:
+ type: string
+ enum:
+ - PENDING
+ - COMPLETED
+ - FAILED
+ description: Status of registration
+ errors:
+ type: array
+ description: List of Errors in case of request validation / processing failure in the server.
+ items:
+ type: object
+ properties:
+ errorCode:
+ type: string
+ enum:
+ - invalid_transaction
+ - unknown_error
+ errorMessage:
+ type: string
+ enum:
+ - invalid_transaction
+ - unknown_error
+ examples:
+ Example 1:
+ value:
+ responseTime: '2023-11-03T11:03:49.770Z'
+ response:
+ status: COMPLETED
+ errors: []
+ servers:
+ - url: 'https://signup.collab.mosip.net/v1/signup'
+ /reset-password:
+ post:
+ tags:
+ - UI
+ summary: Reset password Endpoint
+ description: |-
+ Endpoint to reset password for already registered users.
+
+
+ 1. TransactionId from the cookie is validated.
+ 2. identifier in the request MUST match the identifier stored in the cache.
+ 3. Retrieve the identity from credential-service using the identifier.
+ 4. Fetch the uin from the retrieved identity and use to call the updateIdentity endpoint.
+ 5. Generate password hash for the provided new password.
+ 6. On success, return status as PENDING
+ 7. In Failure, response is set to null, errors list if set with specific errorCode.
+
+ registration/status endpoint should be invoked to get the latest status of the pwd reset.
+ operationId: post-reset-password
+ parameters:
+ - name: X-XSRF-TOKEN
+ in: header
+ description: CSRF token as set in cookie key 'XSRF-TOKEN'
+ required: true
+ schema:
+ type: string
+ - name: VERIFIED_TRANSACTION_ID
+ in: cookie
+ description: Transaction Id set after successful verify-challenge response
+ required: true
+ schema:
+ type: string
+ requestBody:
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ requestTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ request:
+ type: object
+ properties:
+ identifier:
+ type: string
+ password:
+ type: string
+ required:
+ - identifier
+ - password
+ required:
+ - requestTime
+ - request
+ responses:
+ '200':
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: object
+ properties:
+ responseTime:
+ type: string
+ description: Current date and time when the request is sent
+ format: date-time
+ response:
+ type: object
+ properties:
+ status:
+ type: string
+ enum:
+ - PENDING
+ - COMPLETED
+ errors:
+ type: array
+ items:
+ type: object
+ properties:
+ errorCode:
+ type: string
+ enum:
+ - invalid_transaction
+ - invalid_identifier
+ - invalid_password
+ - invalid_request
+ - reset_pwd_failed
+ errorMessage:
+ type: string
+ enum:
+ - invalid_transaction
+ - invalid_identifier
+ - invalid_password
+ - invalid_request
+ - reset_pwd_failed
+ servers:
+ - url: 'https://signup.collab.mosip.net/v1/signup'
+tags:
+ - name: UI
+ description: UI related API.
+components:
+ securitySchemes:
+ Authorization-Bearer:
+ type: http
+ scheme: bearer
+ schemas:
+ UIConfigMap:
+ type: object
+ title: UIConfigMap
+ description: Key-value pairs as configured in signup server.
+ properties:
+ identifier.pattern:
+ type: string
+ identifier.prefix:
+ type: string
+ captcha.site.key:
+ type: string
+ otp.length:
+ type: integer
+ otp.secret:
+ type: boolean
+ password.pattern:
+ type: string
+ challenge.timeout:
+ type: integer
+ resend.attempts:
+ type: integer
+ resend.delay:
+ type: integer
+ fullname.pattern:
+ type: string
+ status.request.delay:
+ type: integer
+ status.request.limit:
+ type: integer
+ popup.timeout:
+ type: integer
+ identifier.allowed.characters:
+ type: string
+ identifier.length.min:
+ type: integer
+ identifier.length.max:
+ type: integer
+ fullname.allowed.characters:
+ type: string
+ fullname.length.min:
+ type: integer
+ fullname.length.max:
+ type: integer
+ otp.blocked:
+ type: integer
+ description: 'Number of seconds, a mobile number will not be allowed to register.'
+ ChallengeInfo:
+ type: object
+ title: ChallengeInfo
+ description: Model to take any type of challenge from the end user as part of challenge verification request.
+ properties:
+ challenge:
+ type: string
+ description: Actual challenge as string.
+ format:
+ type: string
+ enum:
+ - alpha-numeric
+ - base64url-encoded-json
+ description: Format of the challenge provided.
+ type:
+ type: string
+ enum:
+ - OTP
+ - KBA
+ required:
+ - challenge
+ - format
+ - type
+ UserInfoMap:
+ type: object
+ title: UserInfoMap
+ properties:
+ fullName:
+ type: array
+ items:
+ $ref: '#/components/schemas/LanguageTaggedValue'
+ phone:
+ type: string
+ preferredLang:
+ type: string
+ required:
+ - fullName
+ - phone
+ LanguageTaggedValue:
+ type: object
+ title: LanguageTaggedValue
+ properties:
+ language:
+ type: string
+ value:
+ type: string
diff --git a/docs/id-schema.json b/docs/id-schema.json
new file mode 100644
index 00000000..b4347d09
--- /dev/null
+++ b/docs/id-schema.json
@@ -0,0 +1,193 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "Identity schema for sign up",
+ "additionalProperties": false,
+ "title": "signup identity",
+ "type": "object",
+ "definitions": {
+ "simpleType": {
+ "uniqueItems": true,
+ "additionalItems": false,
+ "type": "array",
+ "items": {
+ "additionalProperties": false,
+ "type": "object",
+ "required": [
+ "language",
+ "value"
+ ],
+ "properties": {
+ "language": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "documentType": {
+ "additionalProperties": false,
+ "type": "object",
+ "properties": {
+ "format": {
+ "type": "string"
+ },
+ "type": {
+ "type": "string"
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ "biometricsType": {
+ "additionalProperties": false,
+ "type": "object",
+ "properties": {
+ "format": {
+ "type": "string"
+ },
+ "version": {
+ "type": "number",
+ "minimum": 0
+ },
+ "value": {
+ "type": "string"
+ }
+ }
+ },
+ "hashType": {
+ "additionalProperties": false,
+ "type": "object",
+ "properties": {
+ "hash": {
+ "type": "string"
+ },
+ "salt": {
+ "type": "string"
+ }
+ }
+ }
+ },
+ "properties": {
+ "identity": {
+ "additionalProperties": false,
+ "type": "object",
+ "required": [
+ "IDSchemaVersion",
+ "fullName",
+ "phone",
+ "password",
+ "preferredLang",
+ "registrationType"
+ ],
+ "properties": {
+ "UIN": {
+ "bioAttributes": [],
+ "fieldCategory": "none",
+ "format": "none",
+ "type": "string",
+ "fieldType": "default"
+ },
+ "IDSchemaVersion": {
+ "bioAttributes": [],
+ "fieldCategory": "none",
+ "format": "none",
+ "type": "number",
+ "fieldType": "default",
+ "minimum": 0
+ },
+ "selectedHandles" : {
+ "fieldCategory": "none",
+ "format": "none",
+ "type": "array",
+ "items" : { "type" : "string" },
+ "fieldType": "default"
+ },
+ "fullName": {
+ "bioAttributes": [],
+ "validators": [
+ {
+ "validator": "^(?=.{3,50}$).",
+ "arguments": [],
+ "type": "regex"
+ }
+ ],
+ "fieldCategory": "pvt",
+ "format": "none",
+ "fieldType": "default",
+ "$ref": "#/definitions/simpleType"
+ },
+ "phone": {
+ "bioAttributes": [],
+ "validators": [
+ {
+ "validator": "^[+]91([0-9]{8,9})$",
+ "arguments": [],
+ "type": "regex"
+ }
+ ],
+ "fieldCategory": "pvt",
+ "format": "none",
+ "type": "string",
+ "fieldType": "default",
+ "requiredOn" : "",
+ "handle" : true
+ },
+ "password": {
+ "bioAttributes": [],
+ "validators": [],
+ "fieldCategory": "pvt",
+ "format": "none",
+ "fieldType": "default",
+ "$ref": "#/definitions/hashType"
+ },
+ "preferredLang": {
+ "bioAttributes": [],
+ "validators": [
+ {
+ "validator": "(^eng$)",
+ "arguments": [],
+ "type": "regex"
+ }
+ ],
+ "fieldCategory": "pvt",
+ "format": "none",
+ "fieldType": "default",
+ "type": "string"
+ },
+ "registrationType": {
+ "bioAttributes": [],
+ "validators": [
+ {
+ "validator": "^L[1-2]{1}$",
+ "arguments": [],
+ "type": "regex"
+ }
+ ],
+ "fieldCategory": "pvt",
+ "format": "none",
+ "fieldType": "default",
+ "type": "string"
+ },
+ "phoneVerified": {
+ "bioAttributes": [],
+ "validators": [],
+ "fieldCategory": "pvt",
+ "format": "none",
+ "fieldType": "default",
+ "type": "boolean"
+ },
+ "updatedAt": {
+ "bioAttributes": [],
+ "validators": [],
+ "fieldCategory": "pvt",
+ "format": "none",
+ "fieldType": "default",
+ "type": "number"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/postman-collections/signup_001.postman_collection.json b/docs/postman-collections/signup_001.postman_collection.json
index b0464dbb..e2ed82db 100644
--- a/docs/postman-collections/signup_001.postman_collection.json
+++ b/docs/postman-collections/signup_001.postman_collection.json
@@ -68,7 +68,7 @@
],
"body": {
"mode": "raw",
- "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"identifier\": \"+855{{randomPhoneNumber}}\",\n \"captchaToken\": \"\",\n \"regenerate\" : false,\n \"locale\" : \"eng\",\n \"purpose\" : \"REGISTRATION\"\n }\n}",
+ "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"identifier\": \"+855{{randomPhoneNumber}}\",\n \"captchaToken\": \"\",\n \"regenerateChallenge\" : false,\n \"locale\" : \"eng\",\n \"purpose\" : \"REGISTRATION\"\n }\n}",
"options": {
"raw": {
"language": "json"
@@ -251,7 +251,7 @@
],
"body": {
"mode": "raw",
- "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"identifier\": \"+855{{randomPhoneNumber}}\",\n \"captchaToken\": \"\",\n \"regenerate\" : false,\n \"purpose\" : \"RESET_PASSWORD\"\n }\n}",
+ "raw": "{\n \"requestTime\": \"{{$isoTimestamp}}\",\n \"request\": {\n \"identifier\": \"+855{{randomPhoneNumber}}\",\n \"captchaToken\": \"\",\n \"regenerateChallenge\" : false,\n \"purpose\" : \"RESET_PASSWORD\"\n }\n}",
"options": {
"raw": {
"language": "json"
diff --git a/docs/signup-with-mosip-id-repo.png b/docs/signup-with-mosip-id-repo.png
new file mode 100644
index 00000000..7698b846
Binary files /dev/null and b/docs/signup-with-mosip-id-repo.png differ
diff --git a/helm/delete-all.sh b/helm/delete-all.sh
index e713d14a..3f338a74 100755
--- a/helm/delete-all.sh
+++ b/helm/delete-all.sh
@@ -13,7 +13,7 @@ function Deleting_All() {
helm -n $SOFTHSM_NS delete softhsm-signup
- declare -a module=("signup"
+ declare -a module=("signup-service"
"signup-ui"
)
@@ -35,4 +35,4 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
set -o nounset ## set -u : exit the script if you try to use an uninitialised variable
set -o errtrace # trace ERR through 'time command' and other functions
set -o pipefail # trace ERR through pipes
-Deleting_All # calling function
\ No newline at end of file
+Deleting_All # calling function
diff --git a/helm/install-all.sh b/helm/install-all.sh
index a229d89e..8b424c1d 100755
--- a/helm/install-all.sh
+++ b/helm/install-all.sh
@@ -13,7 +13,7 @@ function installing_All() {
helm repo add mosip https://mosip.github.io/mosip-helm
helm repo update
- declare -a module=("signup"
+ declare -a module=("signup-service"
"signup-ui"
)
diff --git a/helm/restart-all.sh b/helm/restart-all.sh
index f88f5c12..467f53c3 100755
--- a/helm/restart-all.sh
+++ b/helm/restart-all.sh
@@ -10,7 +10,7 @@ fi
function Restarting_All() {
ROOT_DIR=`pwd`
- declare -a module=("signup"
+ declare -a module=("signup-service"
"signup-ui"
)
@@ -32,4 +32,4 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
set -o nounset ## set -u : exit the script if you try to use an uninitialised variable
set -o errtrace # trace ERR through 'time command' and other functions
set -o pipefail # trace ERR through pipes
-Restarting_All # calling function
\ No newline at end of file
+Restarting_All # calling function
diff --git a/helm/signup-service/Chart.yaml b/helm/signup-service/Chart.yaml
index 394c38c4..090c8f54 100644
--- a/helm/signup-service/Chart.yaml
+++ b/helm/signup-service/Chart.yaml
@@ -2,7 +2,7 @@ apiVersion: v2
name: signup
description: A Helm chart for DGTDept signup-service module
type: application
-version: 1.0.1
+version: 1.0.2
appVersion: ""
dependencies:
- name: common
diff --git a/helm/signup-service/README.md b/helm/signup-service/README.md
index 53f65bc5..8d74f729 100644
--- a/helm/signup-service/README.md
+++ b/helm/signup-service/README.md
@@ -38,3 +38,4 @@ Refer [Commons](https://docs.mosip.io/1.2.0/modules/commons).
```
./delete.sh
```
+
diff --git a/helm/signup-service/copy_cm.sh b/helm/signup-service/copy_cm.sh
index 68782f50..b1633658 100755
--- a/helm/signup-service/copy_cm.sh
+++ b/helm/signup-service/copy_cm.sh
@@ -7,7 +7,6 @@ function copying_cm() {
DST_NS=signup
$COPY_UTIL configmap global default $DST_NS
- $COPY_UTIL configmap artifactory-share artifactory $DST_NS
$COPY_UTIL configmap config-server-share config-server $DST_NS
$COPY_UTIL configmap softhsm-signup-share softhsm $DST_NS
return 0
diff --git a/helm/signup-service/install.sh b/helm/signup-service/install.sh
index fccd0b08..4bb0599e 100755
--- a/helm/signup-service/install.sh
+++ b/helm/signup-service/install.sh
@@ -7,13 +7,13 @@ if [ $# -ge 1 ] ; then
fi
SOFTHSM_NS=softhsm
-SOFTHSM_CHART_VERSION=12.0.2
+SOFTHSM_CHART_VERSION=12.0.1
echo Create $SOFTHSM_NS namespace
kubectl create ns $SOFTHSM_NS
NS=signup
-CHART_VERSION=1.0.1
+CHART_VERSION=1.0.2
SIGNUP_HOST=$(kubectl get cm global -o jsonpath={.data.mosip-signup-host})
@@ -67,6 +67,7 @@ function installing_signup() {
echo $SIGNUP_CLIENT_SECRET_VALUE
kubectl patch secret keycloak-client-secrets --namespace=config-server --type=json -p='[{"op": "add", "path": "/data/'$SIGNUP_CLIENT_SECRET_KEY'", "value": "'$SIGNUP_CLIENT_SECRET_VALUE'"}]'
+ kubectl -n config-server set env --keys=mosip_signup_client_secret --from secret/keycloak-client-secrets deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_
kubectl -n config-server set env --keys=mosip-signup-host --from configmap/global deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_
kubectl -n config-server set env --keys=signup-captcha-site-key --from secret/signup-captcha deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_
kubectl -n config-server set env --keys=signup-captcha-secret-key --from secret/signup-captcha deployment/config-server --prefix=SPRING_CLOUD_CONFIG_SERVER_OVERRIDES_
@@ -89,7 +90,7 @@ function installing_signup() {
fi
echo Installing signup
- helm -n $NS install signup mosip/signup-service --version $CHART_VERSION $ENABLE_INSECURE
+ helm -n $NS install signup mosip/signup --version $CHART_VERSION $ENABLE_INSECURE
kubectl -n $NS get deploy -o name | xargs -n1 -t kubectl -n $NS rollout status
diff --git a/helm/signup-service/keycloak-init.sh b/helm/signup-service/keycloak-init.sh
index 80166785..2d7ef435 100755
--- a/helm/signup-service/keycloak-init.sh
+++ b/helm/signup-service/keycloak-init.sh
@@ -7,7 +7,7 @@ if [ $# -ge 1 ] ; then
fi
NS=signup
-CHART_VERSION=12.0.1-B2
+CHART_VERSION=12.0.1
COPY_UTIL=./copy_cm_func.sh
helm repo add mosip https://mosip.github.io/mosip-helm
diff --git a/helm/signup-service/templates/_helpers.tpl b/helm/signup-service/templates/_helpers.tpl
index 1becb8f9..aaf70864 100644
--- a/helm/signup-service/templates/_helpers.tpl
+++ b/helm/signup-service/templates/_helpers.tpl
@@ -57,4 +57,15 @@ Return podAnnotations
{{- end }}
{{- end -}}
+User
+{{/*
+Baseurl for artifactory service
+*/}}
+{{- define "artifactory.baseUrl" -}}
+{{ printf "http://artifactory.artifactory:%s" (.Values.service.port | toString) }}
+{{- end -}}
+
+
+
+
diff --git a/helm/signup-service/templates/configmap-share.yaml b/helm/signup-service/templates/configmap-share.yaml
new file mode 100644
index 00000000..0ca93178
--- /dev/null
+++ b/helm/signup-service/templates/configmap-share.yaml
@@ -0,0 +1,25 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ labels:
+ {{- include "common.labels.standard" . | nindent 4 }}
+ app.kubernetes.io/component: artifactory
+ name: artifactory-share
+ {{- if .Values.commonAnnotations }}
+ annotations:
+ {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }}
+ {{- end }}
+data:
+ artifactory_url_env: {{ include "artifactory.baseUrl" . | quote }}
+ iam_adapter_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.iamAdapter | quote }}
+ iam_adapter_regproc_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.iamAdapterRegproc | quote }}
+ iam_adapter_regproc_ext_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.iamAdapterRegprocExt | quote }}
+ zip_file_path: {{ .Values.artifacts.hsmClientZip | quote }}
+ cache_provider_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.cacheProvider | quote }}
+ runtime_dep_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.runtimeDep | quote }}
+ regproc_jars_env: {{ .Values.artifacts.regprocJars | quote }}
+ preregistration_i18n_bundle_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.preregistrationBundleUrl | quote }}
+ virusscanner_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.virusscannerUrl | quote }}
+ auth_wrapper_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.authwrapperUrl | quote }}
+ esignet_wrapper_url_env: {{ printf "%s%s" (include "artifactory.baseUrl" .) .Values.artifacts.esignetauthwrapperUrl | quote }}
+
diff --git a/helm/signup-service/values.yaml b/helm/signup-service/values.yaml
index 6aaed445..17edc4af 100644
--- a/helm/signup-service/values.yaml
+++ b/helm/signup-service/values.yaml
@@ -52,8 +52,8 @@ service:
image:
registry: docker.io
- repository: mosipdev/signup-service
- tag: develop
+ repository: mosipid/signup-service
+ tag: 1.0.2
## Specify a imagePullPolicy
## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
## ref: http://kubernetes.io/docs/user-guide/images/#pre-pulling-images
@@ -127,10 +127,10 @@ resources:
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
limits:
cpu: 500m
- memory: 2250Mi
+ memory: 3000Mi
requests:
- cpu: 100m
- memory: 1500Mi
+ cpu: 500m
+ memory: 3000Mi
additionalResources:
## Specify any JAVA_OPTS string here. These typically will be specified in conjunction with above resources
@@ -443,6 +443,21 @@ metrics:
# labels:
# severity: error
rules: []
+## There are various jars and libs in artifactory. Listing their locations here. The locations are vis-a-vis
+## /usr/share/nginx/html/artifactory path in artifactory docker
+artifacts:
+ iamAdapter: /artifactory/libs-release-local/io/mosip/kernel/kernel-auth-adapter-lite.jar
+ iamAdapterRegproc: /artifactory/libs-release-local/io/mosip/kernel/kernel-auth-adapter.jar
+ iamAdapterRegprocExt: /artifactory/libs-release-local/io/mosip/kernel/kernel-auth-adapter.jar
+ hsmClientZip: /artifactory/libs-release-local/hsm/client.zip
+ cacheProvider: /artifactory/libs-release-local/cache/cache-provider.jar
+ runtimeDep: /artifactory/libs-release-local/io/mosip/kernel/
+ regprocJars: /artifactory/libs-release-local/clamav/kernel-virusscanner-clamav.jar
+ runtimeDepUrl: /artifactory/libs-release-local/io/mosip/kernel/
+ preregistrationBundleUrl: /artifactory/libs-release-local/i18n/pre-registration-i18n-bundle.zip
+ virusscannerUrl: /artifactory/libs-release-local/clamav/kernel-virusscanner-clamav.jar
+ authwrapperUrl: /artifactory/libs-release-local/idp/idp-auth-wrapper/authentication-wrapper.jar
+ esignetauthwrapperUrl: /artifactory/libs-release-local/esignet/esignet-wrapper.zip
signup:
## Only internal access
diff --git a/helm/signup-ui/Chart.yaml b/helm/signup-ui/Chart.yaml
index 799422c8..8394db0a 100644
--- a/helm/signup-ui/Chart.yaml
+++ b/helm/signup-ui/Chart.yaml
@@ -2,7 +2,7 @@ apiVersion: v2
name: signup-ui
description: A Helm chart for DGTDept SIGNUP UI module
type: application
-version: 1.0.1
+version: 1.0.2
appVersion: ""
dependencies:
- name: common
diff --git a/helm/signup-ui/copy_cm.sh b/helm/signup-ui/copy_cm.sh
index ac43caac..87fb95c4 100755
--- a/helm/signup-ui/copy_cm.sh
+++ b/helm/signup-ui/copy_cm.sh
@@ -7,7 +7,6 @@ function copying_cm() {
DST_NS=signup
$COPY_UTIL configmap global default $DST_NS
- $COPY_UTIL configmap artifactory-share artifactory $DST_NS
$COPY_UTIL configmap config-server-share config-server $DST_NS
$COPY_UTIL configmap softhsm-esignet-share softhsm $DST_NS
return 0
diff --git a/helm/signup-ui/install.sh b/helm/signup-ui/install.sh
index ac071db2..dc5e08fd 100755
--- a/helm/signup-ui/install.sh
+++ b/helm/signup-ui/install.sh
@@ -7,7 +7,7 @@ if [ $# -ge 1 ] ; then
fi
NS=signup
-CHART_VERSION=1.0.1
+CHART_VERSION=1.0.2
echo Create $NS namespace
kubectl create ns $NS
diff --git a/helm/signup-ui/templates/configmap.yaml b/helm/signup-ui/templates/configmap.yaml
index 52e64f97..a7e56ef5 100644
--- a/helm/signup-ui/templates/configmap.yaml
+++ b/helm/signup-ui/templates/configmap.yaml
@@ -34,8 +34,8 @@ data:
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
- location /v1/esignet {
- proxy_pass http://{{ .Values.signup_ui.signup_service_host }}/v1/esignet;
+ location /v1/signup {
+ proxy_pass http://{{ .Values.signup_ui.signup_service_host }}/v1/signup;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
@@ -117,4 +117,4 @@ data:
{{ $key }}: {{ $value | quote }}
{{- end }}
{{- end }}
- {{- end }}
\ No newline at end of file
+ {{- end }}
diff --git a/helm/signup-ui/values.yaml b/helm/signup-ui/values.yaml
index 158d2bec..d669068b 100755
--- a/helm/signup-ui/values.yaml
+++ b/helm/signup-ui/values.yaml
@@ -51,8 +51,8 @@ service:
image:
registry: docker.io
- repository: mosipdev/signup-ui
- tag: develop
+ repository: mosipid/signup-ui
+ tag: 1.0.2
## Specify a imagePullPolicy
## Defaults to 'Always' if image tag is 'latest', else set to 'IfNotPresent'
diff --git a/pom.xml b/pom.xml
index 4e4b441e..47f9e114 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
4.0.0
io.mosip.signup
signup-parent
- 1.0.1-SNAPSHOT
+ 1.0.2
pom
esignet-signup
Parent project of MOSIP e-Signet
diff --git a/signup-service/Dockerfile b/signup-service/Dockerfile
index d35a043c..225696dd 100644
--- a/signup-service/Dockerfile
+++ b/signup-service/Dockerfile
@@ -9,55 +9,27 @@ LABEL commit_hash=${COMMIT_HASH}
LABEL commit_id=${COMMIT_ID}
LABEL build_time=${BUILD_TIME}
-# can be passed during Docker build as build time environment for github branch to pickup configuration from.
-ARG spring_config_label
-
-# can be passed during Docker build as build time environment for spring profiles active
+# can be passed during Docker build as build time environment for github branch to pickup configuration from | spring profiles active | config server URL | glowroot and artifactory URL respectively .
+ARG spring_config_label
ARG active_profile
-
-# can be passed during Docker build as build time environment for config server URL
-ARG spring_config_url
-
-# can be passed during Docker build as build time environment for glowroot
+ARG spring_config_url
ARG is_glowroot
-
-# can be passed during Docker build as build time environment for artifactory URL
ARG artifactory_url
-# environment variable to pass active profile such as DEV, QA etc at docker runtime
+# environment variable to pass active profile such as DEV, QA etc at docker runtime | github branch to pickup configuration from, at docker runtime | spring configuration url, at docker runtime | glowroot, at docker runtime | artifactory url, at docker runtime and iam_adapter url, at docker runtime, respectively.
ENV active_profile_env=${active_profile}
-
-# environment variable to pass github branch to pickup configuration from, at docker runtime
ENV spring_config_label_env=${spring_config_label}
-
-# environment variable to pass spring configuration url, at docker runtime
ENV spring_config_url_env=${spring_config_url}
-
-# environment variable to pass glowroot, at docker runtime
ENV is_glowroot_env=${is_glowroot}
-
-# environment variable to pass artifactory url, at docker runtime
ENV artifactory_url_env=${artifactory_url}
+ENV iam_adapter_url_env=${iam_adapter_url}
# can be passed during Docker build as build time environment for github branch to pickup configuration from.
ARG container_user=mosip
-
-# can be passed during Docker build as build time environment for github branch to pickup configuration from.
ARG container_user_group=mosip
-
-# can be passed during Docker build as build time environment for github branch to pickup configuration from.
ARG container_user_uid=1001
-
-# can be passed during Docker build as build time environment for github branch to pickup configuration from.
ARG container_user_gid=1001
-# install packages and create user
-RUN apt-get -y update \
-&& apt-get install -y unzip file sudo \
-&& groupadd -g ${container_user_gid} ${container_user_group} \
-&& useradd -u ${container_user_uid} -g ${container_user_group} -s /bin/sh -m ${container_user} \
-&& adduser ${container_user} sudo
-
# set working directory for the user
WORKDIR /home/${container_user}
@@ -65,14 +37,18 @@ ENV work_dir=/home/${container_user}
ARG loader_path=${work_dir}/additional_jars/
-RUN mkdir -p ${loader_path}
-
ENV loader_path_env=${loader_path}
COPY ./target/signup-service-*.jar signup-service.jar
-# change permissions of file inside working dir
-RUN chown -R ${container_user}:${container_user} /home/${container_user}
+## install packages, create user and change permissions of file inside working dir
+RUN apt-get -y update \
+&& apt-get install -y unzip file sudo \
+&& groupadd -g ${container_user_gid} ${container_user_group} \
+&& useradd -u ${container_user_uid} -g ${container_user_group} -s /bin/sh -m ${container_user} \
+&& adduser ${container_user} sudo \
+&& mkdir -p ${loader_path} \
+&& chown -R ${container_user}:${container_user} /home/${container_user}
# select container user for all tasks
USER ${container_user_uid}:${container_user_gid}
diff --git a/signup-service/pom.xml b/signup-service/pom.xml
index b41af416..8f9a0c73 100644
--- a/signup-service/pom.xml
+++ b/signup-service/pom.xml
@@ -15,7 +15,7 @@
io.mosip.signup
signup-service
- 1.0.1-SNAPSHOT
+ 1.0.2
signup-service
Sign Up Service
https://github.com/DGTDept/esignet-signup
@@ -115,7 +115,7 @@
io.mosip.esignet
esignet-core
- 1.3.0-SNAPSHOT
+ 1.4.1-SNAPSHOT
org.springframework.boot
@@ -142,7 +142,7 @@
org.bitbucket.b_c
jose4j
- 0.9.3
+ 0.9.4
org.springframework.boot
@@ -172,7 +172,7 @@
io.mosip.esignet
esignet-integration-api
- 1.3.0-SNAPSHOT
+ 1.4.1-SNAPSHOT
org.mockito
diff --git a/signup-service/src/main/java/io/mosip/signup/SignUpServiceApplication.java b/signup-service/src/main/java/io/mosip/signup/SignUpServiceApplication.java
index 2bdf1986..4ec15691 100644
--- a/signup-service/src/main/java/io/mosip/signup/SignUpServiceApplication.java
+++ b/signup-service/src/main/java/io/mosip/signup/SignUpServiceApplication.java
@@ -1,5 +1,7 @@
package io.mosip.signup;
+import io.mosip.esignet.core.config.RedisCacheConfig;
+import io.mosip.esignet.core.config.SimpleCacheConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@@ -10,7 +12,8 @@
@SpringBootApplication(scanBasePackages = "io.mosip.signup.*," +
"io.mosip.esignet.core.config.RedisCacheConfig," +
"io.mosip.esignet.core.config.SimpleCacheConfig,"+
- "${mosip.auth.adapter.impl.basepackage}")
+ "${mosip.auth.adapter.impl.basepackage}",
+ scanBasePackageClasses = {SimpleCacheConfig.class, RedisCacheConfig.class})
public class SignUpServiceApplication {
public static void main(String[] args) {
diff --git a/signup-service/src/main/java/io/mosip/signup/config/Config.java b/signup-service/src/main/java/io/mosip/signup/config/Config.java
new file mode 100644
index 00000000..6c88acc6
--- /dev/null
+++ b/signup-service/src/main/java/io/mosip/signup/config/Config.java
@@ -0,0 +1,28 @@
+package io.mosip.signup.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.Executor;
+
+@Configuration
+public class Config {
+
+ @Value("${mosip.signup.task.core.pool.size:20}")
+ private int taskCorePoolSize;
+
+ @Value("${mosip.signup.task.max.pool.size:20}")
+ private int taskMaxPoolSize;
+
+ @Bean
+ public Executor taskExecutor() {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setCorePoolSize(taskCorePoolSize);
+ executor.setMaxPoolSize(taskMaxPoolSize);
+ executor.setThreadNamePrefix("MOSIP-SIGNUP-Async-Thread-");
+ executor.initialize();
+ return executor;
+ }
+}
diff --git a/signup-service/src/main/java/io/mosip/signup/controllers/RegistrationController.java b/signup-service/src/main/java/io/mosip/signup/controllers/RegistrationController.java
index e744188f..768c9c7c 100644
--- a/signup-service/src/main/java/io/mosip/signup/controllers/RegistrationController.java
+++ b/signup-service/src/main/java/io/mosip/signup/controllers/RegistrationController.java
@@ -1,5 +1,7 @@
package io.mosip.signup.controllers;
+import io.micrometer.core.annotation.Counted;
+import io.micrometer.core.annotation.Timed;
import io.mosip.esignet.core.dto.RequestWrapper;
import io.mosip.esignet.core.dto.ResponseWrapper;
import io.mosip.esignet.core.util.IdentityProviderUtil;
@@ -70,6 +72,7 @@ public ResponseWrapper verifyChallenge(@Valid @RequestB
return responseWrapper;
}
+
@PostMapping("/register")
public ResponseWrapper register(@Valid @RequestBody RequestWrapper requestWrapper,
@Valid @NotBlank(message = ErrorConstants.INVALID_TRANSACTION)
diff --git a/signup-service/src/main/java/io/mosip/signup/controllers/ResetPasswordController.java b/signup-service/src/main/java/io/mosip/signup/controllers/ResetPasswordController.java
new file mode 100644
index 00000000..3571941e
--- /dev/null
+++ b/signup-service/src/main/java/io/mosip/signup/controllers/ResetPasswordController.java
@@ -0,0 +1,54 @@
+package io.mosip.signup.controllers;
+
+
+import io.micrometer.core.annotation.Timed;
+import io.mosip.esignet.core.dto.RequestWrapper;
+import io.mosip.esignet.core.dto.ResponseWrapper;
+import io.mosip.esignet.core.util.IdentityProviderUtil;
+import io.mosip.signup.dto.RegistrationStatusResponse;
+import io.mosip.signup.dto.ResetPasswordRequest;
+import io.mosip.signup.dto.SettingsResponse;
+import io.mosip.signup.exception.SignUpException;
+import io.mosip.signup.helper.AuditHelper;
+import io.mosip.signup.services.RegistrationService;
+import io.mosip.signup.util.AuditEvent;
+import io.mosip.signup.util.AuditEventType;
+import io.mosip.signup.util.ErrorConstants;
+import io.mosip.signup.util.SignUpConstants;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import java.util.Map;
+
+import static io.mosip.signup.util.SignUpConstants.EMTPY;
+
+@Slf4j
+@RestController
+public class ResetPasswordController {
+
+ @Autowired
+ RegistrationService registrationService;
+
+ @Autowired
+ AuditHelper auditHelper;
+
+ @PostMapping("/reset-password")
+ public ResponseWrapper resetPassword(@Valid @RequestBody RequestWrapper requestWrapper,
+ @Valid @NotBlank(message = ErrorConstants.INVALID_TRANSACTION)
+ @CookieValue(value = SignUpConstants.VERIFIED_TRANSACTION_ID, defaultValue = EMTPY) String transactionId){
+ ResponseWrapper responseWrapper = new ResponseWrapper<>();
+ try{
+ responseWrapper.setResponse(registrationService.updatePassword(requestWrapper.getRequest(), transactionId));
+ }catch (SignUpException signUpException){
+ auditHelper.sendAuditTransaction(AuditEvent.RESET_PASSWORD, AuditEventType.ERROR, transactionId, signUpException);
+ throw signUpException;
+ }
+ auditHelper.sendAuditTransaction(AuditEvent.RESET_PASSWORD, AuditEventType.SUCCESS, transactionId, null);
+ responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime());
+ return responseWrapper;
+ }
+}
diff --git a/signup-service/src/main/java/io/mosip/signup/controllers/SignUpController.java b/signup-service/src/main/java/io/mosip/signup/controllers/SignUpController.java
index 8af399ea..7b264891 100644
--- a/signup-service/src/main/java/io/mosip/signup/controllers/SignUpController.java
+++ b/signup-service/src/main/java/io/mosip/signup/controllers/SignUpController.java
@@ -1,35 +1,18 @@
package io.mosip.signup.controllers;
-
-import io.mosip.esignet.core.dto.RequestWrapper;
import io.mosip.esignet.core.dto.ResponseWrapper;
import io.mosip.esignet.core.util.IdentityProviderUtil;
import io.mosip.signup.dto.*;
-import io.mosip.signup.exception.SignUpException;
-import io.mosip.signup.helper.AuditHelper;
-import io.mosip.signup.services.RegistrationService;
-import io.mosip.signup.util.*;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
-import javax.validation.Valid;
-import javax.validation.constraints.NotBlank;
import java.util.Map;
-import static io.mosip.signup.util.SignUpConstants.EMTPY;
-
@Slf4j
@RestController
public class SignUpController {
- @Autowired
- RegistrationService registrationService;
-
- @Autowired
- AuditHelper auditHelper;
-
@Value("#{${mosip.signup.ui.config.key-values}}")
private Map signUpUIConfigMap;
@@ -42,20 +25,4 @@ public ResponseWrapper getSignUpDetails() {
responseWrapper.setResponse(response);
return responseWrapper;
}
-
- @PostMapping("/reset-password")
- public ResponseWrapper resetPassword(@Valid @RequestBody RequestWrapper requestWrapper,
- @Valid @NotBlank(message = ErrorConstants.INVALID_TRANSACTION)
- @CookieValue(value = SignUpConstants.VERIFIED_TRANSACTION_ID, defaultValue = EMTPY) String transactionId){
- ResponseWrapper responseWrapper = new ResponseWrapper<>();
- try{
- responseWrapper.setResponse(registrationService.updatePassword(requestWrapper.getRequest(), transactionId));
- }catch (SignUpException signUpException){
- auditHelper.sendAuditTransaction(AuditEvent.RESET_PASSWORD, AuditEventType.ERROR, transactionId, signUpException);
- throw signUpException;
- }
- auditHelper.sendAuditTransaction(AuditEvent.RESET_PASSWORD, AuditEventType.SUCCESS, transactionId, null);
- responseWrapper.setResponseTime(IdentityProviderUtil.getUTCDateTime());
- return responseWrapper;
- }
}
diff --git a/signup-service/src/main/java/io/mosip/signup/dto/GenerateChallengeRequest.java b/signup-service/src/main/java/io/mosip/signup/dto/GenerateChallengeRequest.java
index 7fa20ca8..30170541 100644
--- a/signup-service/src/main/java/io/mosip/signup/dto/GenerateChallengeRequest.java
+++ b/signup-service/src/main/java/io/mosip/signup/dto/GenerateChallengeRequest.java
@@ -13,7 +13,8 @@ public class GenerateChallengeRequest {
private String captchaToken;
@Language(required = false)
private String locale;
- private boolean regenerate;
+ private boolean regenerateChallenge;
+ @io.mosip.signup.validator.Purpose
private Purpose purpose;
}
diff --git a/signup-service/src/main/java/io/mosip/signup/dto/Identity.java b/signup-service/src/main/java/io/mosip/signup/dto/Identity.java
index 2ae16610..eb501fb2 100644
--- a/signup-service/src/main/java/io/mosip/signup/dto/Identity.java
+++ b/signup-service/src/main/java/io/mosip/signup/dto/Identity.java
@@ -33,4 +33,10 @@ public class Identity implements Serializable {
@JsonInclude(JsonInclude.Include.NON_NULL)
private List selectedHandles;
+
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private Boolean phoneVerified;
+
+ @JsonInclude(JsonInclude.Include.NON_NULL)
+ private Long updatedAt;
}
diff --git a/signup-service/src/main/java/io/mosip/signup/dto/RegisterRequest.java b/signup-service/src/main/java/io/mosip/signup/dto/RegisterRequest.java
index 2a0aed12..40ad7a9f 100644
--- a/signup-service/src/main/java/io/mosip/signup/dto/RegisterRequest.java
+++ b/signup-service/src/main/java/io/mosip/signup/dto/RegisterRequest.java
@@ -1,6 +1,7 @@
package io.mosip.signup.dto;
import io.mosip.signup.util.ErrorConstants;
+import io.mosip.signup.validator.Language;
import io.mosip.signup.validator.Password;
import io.mosip.signup.validator.Username;
import lombok.Data;
@@ -25,4 +26,7 @@ public class RegisterRequest {
@NotNull(message = ErrorConstants.INVALID_USERINFO)
private @Valid UserInfoMap userInfo;
+
+ @Language(required = false)
+ private String locale;
}
diff --git a/signup-service/src/main/java/io/mosip/signup/dto/RegistrationTransaction.java b/signup-service/src/main/java/io/mosip/signup/dto/RegistrationTransaction.java
index 2ef282c5..7d6c651c 100644
--- a/signup-service/src/main/java/io/mosip/signup/dto/RegistrationTransaction.java
+++ b/signup-service/src/main/java/io/mosip/signup/dto/RegistrationTransaction.java
@@ -1,13 +1,10 @@
package io.mosip.signup.dto;
import io.mosip.esignet.core.util.IdentityProviderUtil;
-import io.mosip.signup.util.ErrorConstants;
import io.mosip.signup.util.Purpose;
import io.mosip.signup.util.RegistrationStatus;
import lombok.Data;
-import javax.validation.Valid;
-import javax.validation.constraints.Pattern;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
@@ -23,6 +20,7 @@ public class RegistrationTransaction implements Serializable {
private String challengeHash;
private String identifier;
private LocalDateTime startedAt;
+ private int verificationAttempts;
private int challengeRetryAttempts;
private LocalDateTime lastRetryAt;
private String challengeTransactionId;
@@ -43,6 +41,7 @@ public RegistrationTransaction(String identifier, Purpose purpose) {
this.registrationStatus = null;
this.challengeHash = null;
this.challengeRetryAttempts = 0;
+ this.verificationAttempts = 0;
this.lastRetryAt = null;
this.purpose = purpose;
}
@@ -58,6 +57,10 @@ public void increaseAttempt() {
this.lastRetryAt = LocalDateTime.now(ZoneOffset.UTC);
}
+ public void incrementVerificationAttempt() {
+ this.verificationAttempts += 1;
+ }
+
public boolean isValidIdentifier(String inputIdentifier) {
return this.identifier.equals(IdentityProviderUtil.generateB64EncodedHash(IdentityProviderUtil.ALGO_SHA3_256,
inputIdentifier));
diff --git a/signup-service/src/main/java/io/mosip/signup/dto/ResetPasswordRequest.java b/signup-service/src/main/java/io/mosip/signup/dto/ResetPasswordRequest.java
index b5c33773..e5c19980 100644
--- a/signup-service/src/main/java/io/mosip/signup/dto/ResetPasswordRequest.java
+++ b/signup-service/src/main/java/io/mosip/signup/dto/ResetPasswordRequest.java
@@ -1,6 +1,7 @@
package io.mosip.signup.dto;
import io.mosip.signup.validator.Identifier;
+import io.mosip.signup.validator.Language;
import io.mosip.signup.validator.Password;
import lombok.Data;
@@ -12,4 +13,7 @@ public class ResetPasswordRequest {
@Password
private String password;
+
+ @Language(required = false)
+ private String locale;
}
diff --git a/signup-service/src/main/java/io/mosip/signup/helper/NotificationHelper.java b/signup-service/src/main/java/io/mosip/signup/helper/NotificationHelper.java
index 7733131a..cf79a26f 100644
--- a/signup-service/src/main/java/io/mosip/signup/helper/NotificationHelper.java
+++ b/signup-service/src/main/java/io/mosip/signup/helper/NotificationHelper.java
@@ -16,7 +16,9 @@
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
+import java.util.Arrays;
import java.util.Base64;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@@ -33,18 +35,23 @@ public class NotificationHelper {
@Value("${mosip.signup.send-notification.endpoint}")
private String sendNotificationEndpoint;
+ @Value("{${mosip.signup.default-language}")
+ private String defaultLanguage;
- @Async
- public CompletableFuture> sendSMSNotificationAsync
+ @Value("#{${mosip.signup.sms-notification-template.encoded-langcodes}}")
+ private List encodedLangCodes;
+
+ public RestResponseWrapper sendSMSNotification
(String number, String locale, String templateKey, Map params){
- locale = locale != null ? locale : "khm";
- String message = locale.equalsIgnoreCase("eng") ?
- environment.getProperty(templateKey + "." + locale) :
- new String(Base64.getDecoder().decode(environment.getProperty(templateKey + "." + locale)));
+ locale = locale != null ? locale : defaultLanguage;
- if(params != null){
- for (Map.Entry entry: params.entrySet()){
+ String message = encodedLangCodes.contains(locale)?
+ new String(Base64.getDecoder().decode(environment.getProperty(templateKey + "." + locale))):
+ environment.getProperty(templateKey + "." + locale);
+
+ if (params != null && message != null) {
+ for (Map.Entry entry : params.entrySet()) {
message = message.replace(entry.getKey(), entry.getValue());
}
}
@@ -55,10 +62,15 @@ public class NotificationHelper {
restRequestWrapper.setRequesttime(IdentityProviderUtil.getUTCDateTime());
restRequestWrapper.setRequest(notificationRequest);
- return CompletableFuture.supplyAsync(() -> selfTokenRestTemplate
- .exchange(sendNotificationEndpoint,
+ return selfTokenRestTemplate.exchange(sendNotificationEndpoint,
HttpMethod.POST,
new HttpEntity<>(restRequestWrapper),
- new ParameterizedTypeReference>(){}).getBody());
+ new ParameterizedTypeReference>(){}).getBody();
+ }
+
+ @Async
+ public CompletableFuture> sendSMSNotificationAsync
+ (String number, String locale, String templateKey, Map params){
+ return CompletableFuture.supplyAsync(() -> sendSMSNotification(number, locale, templateKey, params));
}
}
diff --git a/signup-service/src/main/java/io/mosip/signup/services/CacheUtilService.java b/signup-service/src/main/java/io/mosip/signup/services/CacheUtilService.java
index e4f1c08e..aa673c2d 100644
--- a/signup-service/src/main/java/io/mosip/signup/services/CacheUtilService.java
+++ b/signup-service/src/main/java/io/mosip/signup/services/CacheUtilService.java
@@ -8,41 +8,40 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
+import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.Locale;
+import java.util.Objects;
@Slf4j
@Service
public class CacheUtilService {
+
@Autowired
CacheManager cacheManager;
//---Setter---
- @Cacheable(value = SignUpConstants.CHALLENGE_GENERATED, key = "#transactionId")
- public RegistrationTransaction setChallengeGeneratedTransaction(String transactionId,
- RegistrationTransaction registrationTransaction) {
- return registrationTransaction;
- }
@CacheEvict(value = SignUpConstants.CHALLENGE_GENERATED, key = "#transactionId")
- @Cacheable(value = SignUpConstants.CHALLENGE_VERIFIED, key = "#transactionId")
- public RegistrationTransaction setChallengeVerifiedTransaction(String transactionId,
+ @Cacheable(value = SignUpConstants.CHALLENGE_VERIFIED, key = "#verifiedTransactionId")
+ public RegistrationTransaction setChallengeVerifiedTransaction(String transactionId, String verifiedTransactionId,
RegistrationTransaction registrationTransaction) {
return registrationTransaction;
}
@CacheEvict(value = SignUpConstants.CHALLENGE_VERIFIED, key = "#transactionId")
- @Cacheable(value = SignUpConstants.REGISTERED_CACHE, key = "#transactionId")
- public RegistrationTransaction setRegisteredTransaction(String transactionId,
- RegistrationTransaction registrationTransaction) {
+ @Cacheable(value = SignUpConstants.STATUS_CHECK, key = "#transactionId")
+ public RegistrationTransaction setStatusCheckTransaction(String transactionId,
+ RegistrationTransaction registrationTransaction) {
return registrationTransaction;
}
- @Cacheable(value = SignUpConstants.BLOCKED_IDENTIFIER, key = "#identifierHash")
- public String blockIdentifier(String identifierHash) {
- return identifierHash;
+ @CacheEvict(value = SignUpConstants.CHALLENGE_GENERATED, key = "#transactionId")
+ @Cacheable(value = SignUpConstants.BLOCKED_IDENTIFIER, key = "#key")
+ public String blockIdentifier(String transactionId, String key, String value) {
+ return value;
}
@Cacheable(value = SignUpConstants.KEYSTORE, key = "#key")
@@ -50,36 +49,50 @@ public String setSecretKey(String key, String secretKey) {
return secretKey;
}
- @Cacheable(value = SignUpConstants.KEY_ALIAS, key = "#key")
+ @CachePut(value = SignUpConstants.KEY_ALIAS, key = "#key")
public String setActiveKeyAlias(String key, String alias) {
return alias;
}
+
+ //----- cache update is separated
+ //----- we are not using @cacheput as @cacheput extends the TTL on cache entry
+
+ public RegistrationTransaction createUpdateChallengeGeneratedTransaction(String transactionId,
+ RegistrationTransaction registrationTransaction) {
+ cacheManager.getCache(SignUpConstants.CHALLENGE_GENERATED).put(transactionId, registrationTransaction); //NOSONAR getCache() will not be returning null here.
+ return registrationTransaction;
+ }
+
+ public void updateStatusCheckTransaction(String transactionId,
+ RegistrationTransaction registrationTransaction) {
+ cacheManager.getCache(SignUpConstants.STATUS_CHECK).put(transactionId, registrationTransaction); //NOSONAR getCache() will not be returning null here.
+ }
+
//---Getter---
public RegistrationTransaction getChallengeGeneratedTransaction(String transactionId) {
- return cacheManager.getCache(SignUpConstants.CHALLENGE_GENERATED).get(transactionId, RegistrationTransaction.class);
+return cacheManager.getCache(SignUpConstants.CHALLENGE_GENERATED).get(transactionId, RegistrationTransaction.class); //NOSONAR getCache() will not be returning null here.
}
public RegistrationTransaction getChallengeVerifiedTransaction(String transactionId) {
- return cacheManager.getCache(SignUpConstants.CHALLENGE_VERIFIED).get(transactionId, RegistrationTransaction.class);
+ return cacheManager.getCache(SignUpConstants.CHALLENGE_VERIFIED).get(transactionId, RegistrationTransaction.class); //NOSONAR getCache() will not be returning null here.
}
- public RegistrationTransaction getRegisteredTransaction(String transactionId) {
- return cacheManager.getCache(SignUpConstants.REGISTERED_CACHE).get(transactionId, RegistrationTransaction.class);
+ public RegistrationTransaction getStatusCheckTransaction(String transactionId) {
+ return cacheManager.getCache(SignUpConstants.STATUS_CHECK).get(transactionId, RegistrationTransaction.class); //NOSONAR getCache() will not be returning null here.
}
public boolean isIdentifierBlocked(String identifier) {
String identifierHash = IdentityProviderUtil.generateB64EncodedHash(IdentityProviderUtil.ALGO_SHA3_256,
identifier.toLowerCase(Locale.ROOT));
- String value = cacheManager.getCache(SignUpConstants.BLOCKED_IDENTIFIER).get(identifierHash, String.class);
- return value == null ? false : true;
+ return cacheManager.getCache(SignUpConstants.BLOCKED_IDENTIFIER).get(identifierHash, String.class) != null; //NOSONAR getCache() will not be returning null here.
}
public String getSecretKey(String keyAlias) {
- return cacheManager.getCache(SignUpConstants.KEYSTORE).get(keyAlias, String.class);
+ return cacheManager.getCache(SignUpConstants.KEYSTORE).get(keyAlias, String.class); //NOSONAR getCache() will not be returning null here.
}
public String getActiveKeyAlias() {
- return cacheManager.getCache(SignUpConstants.KEY_ALIAS).get(CryptoHelper.ALIAS_CACHE_KEY, String.class);
+ return cacheManager.getCache(SignUpConstants.KEY_ALIAS).get(CryptoHelper.ALIAS_CACHE_KEY, String.class); //NOSONAR getCache() will not be returning null here.
}
}
diff --git a/signup-service/src/main/java/io/mosip/signup/services/ChallengeManagerService.java b/signup-service/src/main/java/io/mosip/signup/services/ChallengeManagerService.java
index a2c8bd85..f3927025 100644
--- a/signup-service/src/main/java/io/mosip/signup/services/ChallengeManagerService.java
+++ b/signup-service/src/main/java/io/mosip/signup/services/ChallengeManagerService.java
@@ -1,5 +1,6 @@
package io.mosip.signup.services;
+import io.micrometer.core.annotation.Timed;
import io.mosip.esignet.core.util.IdentityProviderUtil;
import io.mosip.signup.dto.*;
import io.mosip.signup.exception.SignUpException;
@@ -15,6 +16,7 @@
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
+import org.springframework.web.client.RestClientException;
@Service
@Slf4j
@@ -32,13 +34,13 @@ public class ChallengeManagerService {
public String generateChallenge(RegistrationTransaction transaction) throws SignUpException {
- switch (supportedGenerateChallengeType) {
- case "OTP" :
- return generateOTPChallenge(transaction.getChallengeTransactionId());
+ if (supportedGenerateChallengeType.equals("OTP")) {
+ return generateOTPChallenge(transaction.getChallengeTransactionId());
}
throw new SignUpException(ErrorConstants.UNSUPPORTED_CHALLENGE_TYPE);
}
+ @Timed(value = "generateotp.api.timer", percentiles = {0.9})
private String generateOTPChallenge(String challengeTransactionId) {
OtpRequest otpRequest = new OtpRequest();
otpRequest.setKey(challengeTransactionId);
@@ -46,20 +48,26 @@ private String generateOTPChallenge(String challengeTransactionId) {
restRequestWrapper.setRequesttime(IdentityProviderUtil.getUTCDateTime());
restRequestWrapper.setRequest(otpRequest);
- RestResponseWrapper restResponseWrapper = selfTokenRestTemplate
- .exchange(generateChallengeUrl, HttpMethod.POST,
- new HttpEntity<>(restRequestWrapper),
- new ParameterizedTypeReference>() {})
- .getBody();
+ try {
+ RestResponseWrapper restResponseWrapper = selfTokenRestTemplate
+ .exchange(generateChallengeUrl, HttpMethod.POST,
+ new HttpEntity<>(restRequestWrapper),
+ new ParameterizedTypeReference>() {
+ })
+ .getBody();
- if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
- !StringUtils.isEmpty(restResponseWrapper.getResponse().getOtp()) &&
- !restResponseWrapper.getResponse().getOtp().equals("null")) {
- return restResponseWrapper.getResponse().getOtp();
- }
+ if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
+ !StringUtils.isEmpty(restResponseWrapper.getResponse().getOtp()) &&
+ !restResponseWrapper.getResponse().getOtp().equals("null")) {
+ return restResponseWrapper.getResponse().getOtp();
+ }
- log.error("Generate OTP failed with response {}", restResponseWrapper);
- throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
- restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.GENERATE_CHALLENGE_FAILED);
+ log.error("Generate OTP failed with response {}", restResponseWrapper);
+ throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
+ restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.GENERATE_CHALLENGE_FAILED);
+ } catch (RestClientException e) {
+ log.error("Endpoint {} is unreachable.", generateChallengeUrl);
+ throw new SignUpException(ErrorConstants.SERVER_UNREACHABLE);
+ }
}
}
diff --git a/signup-service/src/main/java/io/mosip/signup/services/GoogleRecaptchaValidatorService.java b/signup-service/src/main/java/io/mosip/signup/services/GoogleRecaptchaValidatorService.java
index 281c4f71..b189a823 100644
--- a/signup-service/src/main/java/io/mosip/signup/services/GoogleRecaptchaValidatorService.java
+++ b/signup-service/src/main/java/io/mosip/signup/services/GoogleRecaptchaValidatorService.java
@@ -1,12 +1,12 @@
package io.mosip.signup.services;
+import io.micrometer.core.annotation.Timed;
import io.mosip.esignet.api.spi.CaptchaValidator;
import io.mosip.signup.dto.ReCaptchaResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
@@ -30,6 +30,7 @@ public class GoogleRecaptchaValidatorService implements CaptchaValidator {
@Autowired
private RestTemplate restTemplate;
+ @Timed(value = "validatecaptcha.api.timer", percentiles = {0.9})
@Override
public boolean validateCaptcha(String captchaToken) {
diff --git a/signup-service/src/main/java/io/mosip/signup/services/RegistrationService.java b/signup-service/src/main/java/io/mosip/signup/services/RegistrationService.java
index 4688cec7..57842e97 100644
--- a/signup-service/src/main/java/io/mosip/signup/services/RegistrationService.java
+++ b/signup-service/src/main/java/io/mosip/signup/services/RegistrationService.java
@@ -2,6 +2,7 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
+import io.micrometer.core.annotation.Timed;
import io.mosip.esignet.core.util.IdentityProviderUtil;
import io.mosip.kernel.core.util.HMACUtils2;
import io.mosip.signup.dto.*;
@@ -23,14 +24,16 @@
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
-import javax.crypto.SecretKey;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;
@@ -98,6 +101,9 @@ public class RegistrationService {
@Value("${mosip.signup.challenge.resend-attempt}")
private int resendAttempts;
+ @Value("${mosip.signup.challenge.verification-attempt}")
+ private int verificationAttempts;
+
@Value("${mosip.signup.challenge.resend-delay}")
private long resendDelay;
@@ -116,6 +122,8 @@ public class RegistrationService {
@Value("${mosip.signup.get-registration-status.endpoint}")
private String getRegistrationStatusEndpoint;
+ private final String notificationLogging = "Notification response -> {}";
+
/**
* Generate and regenerate challenge based on the "regenerate" flag in the request.
* if regenerate is false - always creates a new transaction and set-cookie header is sent in the response.
@@ -137,7 +145,7 @@ public GenerateChallengeResponse generateChallenge(GenerateChallengeRequest gene
if(cacheUtilService.isIdentifierBlocked(identifier))
throw new SignUpException(ErrorConstants.IDENTIFIER_BLOCKED);
- if(generateChallengeRequest.isRegenerate() == false) {
+ if(!generateChallengeRequest.isRegenerateChallenge()) {
transactionId = IdentityProviderUtil.createTransactionId(null);
transaction = new RegistrationTransaction(identifier, generateChallengeRequest.getPurpose());
//Need to set cookie only when regenerate is false.
@@ -145,7 +153,8 @@ public GenerateChallengeResponse generateChallenge(GenerateChallengeRequest gene
}
else {
transaction = cacheUtilService.getChallengeGeneratedTransaction(transactionId);
- validateTransaction(transaction, identifier);
+ validateTransaction(transaction, identifier, generateChallengeRequest);
+ transaction.setVerificationAttempts(0);
}
// generate Challenge
@@ -154,17 +163,22 @@ public GenerateChallengeResponse generateChallenge(GenerateChallengeRequest gene
transaction.setChallengeHash(challengeHash);
transaction.increaseAttempt();
transaction.setLocale(generateChallengeRequest.getLocale());
- cacheUtilService.setChallengeGeneratedTransaction(transactionId, transaction);
+ cacheUtilService.createUpdateChallengeGeneratedTransaction(transactionId, transaction);
//Resend attempts exhausted, block the identifier for configured time.
- if(transaction.getChallengeRetryAttempts() > resendAttempts + 1)
- cacheUtilService.blockIdentifier(transaction.getIdentifier());
-
- notificationHelper.sendSMSNotificationAsync(generateChallengeRequest.getIdentifier(), transaction.getLocale(),
- SEND_OTP_SMS_NOTIFICATION_TEMPLATE_KEY, new HashMap<>(){{put("{challenge}", challenge);}})
- .thenAccept(notificationResponseRestResponseWrapper -> {
- log.debug("Notification response -> {}", notificationResponseRestResponseWrapper);
- });
+ if(transaction.getChallengeRetryAttempts() > resendAttempts)
+ cacheUtilService.blockIdentifier(transactionId, transaction.getIdentifier(), "blocked");
+
+ HashMap hashMap = new LinkedHashMap<>();
+ hashMap.put("{challenge}", challenge);
+ RestResponseWrapper notificationResponseRest;
+ try{
+ notificationResponseRest = notificationHelper.sendSMSNotification(generateChallengeRequest.getIdentifier(), transaction.getLocale(),
+ SEND_OTP_SMS_NOTIFICATION_TEMPLATE_KEY, hashMap);
+ log.debug(notificationLogging, notificationResponseRest);
+ }catch (RestClientException e){
+ throw new SignUpException(ErrorConstants.OTP_NOTIFICATION_FAILED);
+ }
return new GenerateChallengeResponse(ActionStatus.SUCCESS);
}
@@ -191,14 +205,18 @@ public VerifyChallengeResponse verifyChallenge(VerifyChallengeRequest verifyChal
if(otpChallengeInfo.isEmpty()) throw new SignUpException(ErrorConstants.INVALID_CHALLENGE);
- String challengeHash = IdentityProviderUtil.generateB64EncodedHash(IdentityProviderUtil.ALGO_SHA3_256,
- otpChallengeInfo.get().getChallenge());
-
if(transaction.getLastRetryToNow() >= challengeTimeout) {
throw new SignUpException(ErrorConstants.CHALLENGE_EXPIRED);
}
+ if(transaction.getVerificationAttempts() >= verificationAttempts){
+ throw new SignUpException(ErrorConstants.TOO_MANY_VERIFY_ATTEMPTS);
+ }
+ String challengeHash = IdentityProviderUtil.generateB64EncodedHash(IdentityProviderUtil.ALGO_SHA3_256,
+ otpChallengeInfo.get().getChallenge());
if(!challengeHash.equals(transaction.getChallengeHash())) {
+ transaction.incrementVerificationAttempt();
+ cacheUtilService.createUpdateChallengeGeneratedTransaction(transactionId, transaction);
log.error("Transaction {} : challenge not match", transactionId);
throw new ChallengeFailedException();
}
@@ -206,11 +224,11 @@ public VerifyChallengeResponse verifyChallenge(VerifyChallengeRequest verifyChal
fetchAndCheckIdentity(transactionId, transaction, verifyChallengeRequest);
//After successful verification of the user, change the transactionId
- transactionId = IdentityProviderUtil.createTransactionId(null);
- addVerifiedCookieInResponse(transactionId, registerTransactionTimeout+statusCheckTransactionTimeout);
+ String verifiedTransactionId = IdentityProviderUtil.createTransactionId(null);
+ addVerifiedCookieInResponse(verifiedTransactionId, registerTransactionTimeout+statusCheckTransactionTimeout);
- cacheUtilService.setChallengeVerifiedTransaction(transactionId, transaction);
- log.debug("Transaction {} : verify challenge status {}", transactionId, ActionStatus.SUCCESS);
+ cacheUtilService.setChallengeVerifiedTransaction(transactionId, verifiedTransactionId, transaction);
+ log.debug("Transaction {} : verify challenge status {}", verifiedTransactionId, ActionStatus.SUCCESS);
return new VerifyChallengeResponse(ActionStatus.SUCCESS);
}
@@ -239,13 +257,14 @@ public RegisterResponse register(RegisterRequest registerRequest, String transac
saveIdentityData(registerRequest, transactionId, transaction);
transaction.setRegistrationStatus(RegistrationStatus.PENDING);
- cacheUtilService.setRegisteredTransaction(transactionId, transaction);
+ cacheUtilService.setStatusCheckTransaction(transactionId, transaction);
+
+ String locale = registerRequest.getLocale() == null ? transaction.getLocale() : registerRequest.getLocale();
- notificationHelper.sendSMSNotificationAsync(registerRequest.getUserInfo().getPhone(), transaction.getLocale(),
+ notificationHelper.sendSMSNotificationAsync(registerRequest.getUserInfo().getPhone(), locale,
REGISTRATION_SMS_NOTIFICATION_TEMPLATE_KEY, null)
- .thenAccept(notificationResponseRestResponseWrapper -> {
- log.debug("Notification response -> {}", notificationResponseRestResponseWrapper);
- });
+ .thenAccept(notificationResponseRestResponseWrapper ->
+ log.debug(notificationLogging, notificationResponseRestResponseWrapper));
RegisterResponse registration = new RegisterResponse();
registration.setStatus(ActionStatus.PENDING);
@@ -253,9 +272,8 @@ public RegisterResponse register(RegisterRequest registerRequest, String transac
return registration;
}
- public RegistrationStatusResponse updatePassword(ResetPasswordRequest resetPasswordRequest,
- String transactionId) throws SignUpException{
-
+ private RegistrationTransaction getTransaction(
+ ResetPasswordRequest resetPasswordRequest, String transactionId) {
log.debug("Transaction {} : start reset password", transactionId);
RegistrationTransaction transaction = cacheUtilService.getChallengeVerifiedTransaction(transactionId);
if(transaction == null) {
@@ -264,16 +282,26 @@ public RegistrationStatusResponse updatePassword(ResetPasswordRequest resetPassw
}
if(!transaction.isValidIdentifier(resetPasswordRequest.getIdentifier().toLowerCase(Locale.ROOT))) {
- log.error("generate-challenge failed: invalid identifier");
+ log.error("reset password failed: invalid identifier");
throw new SignUpException(ErrorConstants.IDENTIFIER_MISMATCH);
}
+ if(!transaction.getPurpose().equals(Purpose.RESET_PASSWORD)) {
+ log.error("reset password failed: purpose mismatch in transaction");
+ throw new SignUpException(ErrorConstants.UNSUPPORTED_PURPOSE);
+ }
+ return transaction;
+ }
+
+ private RestRequestWrapper getRestRequestWrapper(RegistrationTransaction transaction, String transactionId,
+ ResetPasswordRequest resetPasswordRequest ) {
Identity identity = new Identity();
identity.setUIN(cryptoHelper.symmetricDecrypt(transaction.getUin()));
identity.setIDSchemaVersion(idSchemaVersion);
Password password = generateSaltedHash(resetPasswordRequest.getPassword(), transactionId);
identity.setPassword(password);
+ identity.setUpdatedAt(LocalDateTime.now(ZoneOffset.UTC).toEpochSecond(ZoneOffset.UTC));
IdentityRequest identityRequest = new IdentityRequest();
identityRequest.setRegistrationId(transaction.getApplicationId());
@@ -285,34 +313,52 @@ public RegistrationStatusResponse updatePassword(ResetPasswordRequest resetPassw
restRequest.setRequesttime(IdentityProviderUtil.getUTCDateTime());
restRequest.setRequest(identityRequest);
- log.debug("Transaction {} : start reset password", transactionId);
- HttpEntity> resReq = new HttpEntity<>(restRequest);
- RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(identityEndpoint,
- HttpMethod.PATCH,
- resReq,
- new ParameterizedTypeReference>() {}).getBody();
+ return restRequest;
+ }
- if (restResponseWrapper != null && restResponseWrapper.getErrors() != null &&
- !CollectionUtils.isEmpty(restResponseWrapper.getErrors())){
- log.error("Transaction {} : reset password failed with response {}", transactionId, restResponseWrapper);
- throw new SignUpException(restResponseWrapper.getErrors().get(0).getErrorCode());
- }
+ private void verifyIdentityResponseForResetPassword(RestRequestWrapper restRequest, String transactionId ) {
+ try {
+ HttpEntity> resReq = new HttpEntity<>(restRequest);
+ RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(identityEndpoint,
+ HttpMethod.PATCH,
+ resReq,
+ new ParameterizedTypeReference>() {}).getBody();
+
+ if (restResponseWrapper != null && restResponseWrapper.getErrors() != null &&
+ !CollectionUtils.isEmpty(restResponseWrapper.getErrors())){
+ log.error("Transaction {} : reset password failed with response {}", transactionId, restResponseWrapper);
+ throw new SignUpException(restResponseWrapper.getErrors().get(0).getErrorCode());
+ }
- if (restResponseWrapper == null || restResponseWrapper.getResponse() == null){
- log.error("Transaction {} : reset password failed with response {}", transactionId, restResponseWrapper);
- throw new SignUpException(ErrorConstants.RESET_PWD_FAILED);
+ if (restResponseWrapper == null || restResponseWrapper.getResponse() == null){
+ log.error("Transaction {} : reset password failed with response {}", transactionId, restResponseWrapper);
+ throw new SignUpException(ErrorConstants.RESET_PWD_FAILED);
+ }
+ } catch (RestClientException e) {
+ log.error("Endpoint {} is unreachable.", identityEndpoint);
+ throw new SignUpException(ErrorConstants.SERVER_UNREACHABLE);
}
+ }
+
+ public RegistrationStatusResponse updatePassword(ResetPasswordRequest resetPasswordRequest,
+ String transactionId) throws SignUpException{
+ RegistrationTransaction transaction = this.getTransaction(resetPasswordRequest, transactionId);
+ RestRequestWrapper restRequest = this.getRestRequestWrapper(transaction, transactionId, resetPasswordRequest);
+
+ log.debug("Transaction {} : start reset password", transactionId);
+ this.verifyIdentityResponseForResetPassword(restRequest, transactionId);
transaction.getHandlesStatus().put(getHandleRequestId(transaction.getApplicationId(),
"phone", resetPasswordRequest.getIdentifier()), RegistrationStatus.PENDING);
transaction.setRegistrationStatus(RegistrationStatus.PENDING);
- cacheUtilService.setRegisteredTransaction(transactionId, transaction);
+ cacheUtilService.setStatusCheckTransaction(transactionId, transaction);
- notificationHelper.sendSMSNotificationAsync(resetPasswordRequest.getIdentifier(), transaction.getLocale(),
+ String locale = resetPasswordRequest.getLocale() == null ? transaction.getLocale() : resetPasswordRequest.getLocale();
+
+ notificationHelper.sendSMSNotificationAsync(resetPasswordRequest.getIdentifier(), locale,
FORGOT_PASSWORD_SMS_NOTIFICATION_TEMPLATE_KEY, null)
- .thenAccept(notificationResponseRestResponseWrapper -> {
- log.debug("Notification response -> {}", notificationResponseRestResponseWrapper);
- });
+ .thenAccept(notificationResponseRestResponseWrapper ->
+ log.debug(notificationLogging, notificationResponseRestResponseWrapper));
RegistrationStatusResponse resetPassword = new RegistrationStatusResponse();
resetPassword.setStatus(RegistrationStatus.PENDING);
@@ -324,7 +370,7 @@ public RegistrationStatusResponse getRegistrationStatus(String transactionId)
if (transactionId == null || transactionId.isEmpty())
throw new InvalidTransactionException();
- RegistrationTransaction registrationTransaction = cacheUtilService.getRegisteredTransaction(
+ RegistrationTransaction registrationTransaction = cacheUtilService.getStatusCheckTransaction(
transactionId);
if (registrationTransaction == null)
throw new InvalidTransactionException();
@@ -337,9 +383,10 @@ public RegistrationStatusResponse getRegistrationStatus(String transactionId)
registrationTransaction.getHandlesStatus().put(handleRequestId, registrationStatus);
//TODO This is temporary fix, we need to remove this field later from registrationTransaction DTO.
registrationTransaction.setRegistrationStatus(registrationStatus);
+ cacheUtilService.updateStatusCheckTransaction(transactionId, registrationTransaction);
}
}
- registrationTransaction = cacheUtilService.setRegisteredTransaction(transactionId, registrationTransaction);
+ registrationTransaction = cacheUtilService.getStatusCheckTransaction(transactionId);
RegistrationStatusResponse registrationStatusResponse = new RegistrationStatusResponse();
registrationStatusResponse.setStatus(registrationTransaction.getRegistrationStatus());
return registrationStatusResponse;
@@ -347,21 +394,29 @@ public RegistrationStatusResponse getRegistrationStatus(String transactionId)
private void fetchAndCheckIdentity(String transactionId, RegistrationTransaction registrationTransaction,
VerifyChallengeRequest verifyChallengeRequest) {
-
- String endpoint = String.format(getIdentityEndpoint, verifyChallengeRequest.getIdentifier());
- RestResponseWrapper restResponseWrapper = selfTokenRestTemplate
- .exchange(endpoint, HttpMethod.GET, null,
- new ParameterizedTypeReference>() {}).getBody();
-
- if (restResponseWrapper == null) throw new SignUpException(ErrorConstants.FETCH_IDENTITY_FAILED);
-
- switch (registrationTransaction.getPurpose()){
- case REGISTRATION: checkIdentityExists(restResponseWrapper);
- break;
- case RESET_PASSWORD: checkActiveIdentityExists(transactionId, restResponseWrapper, registrationTransaction,
- verifyChallengeRequest);
- break;
- default: throw new SignUpException(ErrorConstants.UNSUPPORTED_PURPOSE);
+ try {
+ String endpoint = String.format(getIdentityEndpoint, verifyChallengeRequest.getIdentifier());
+ RestResponseWrapper restResponseWrapper = selfTokenRestTemplate
+ .exchange(endpoint, HttpMethod.GET, null,
+ new ParameterizedTypeReference>() {
+ }).getBody();
+
+ if (restResponseWrapper == null) throw new SignUpException(ErrorConstants.FETCH_IDENTITY_FAILED);
+
+ switch (registrationTransaction.getPurpose()) {
+ case REGISTRATION:
+ checkIdentityExists(restResponseWrapper);
+ break;
+ case RESET_PASSWORD:
+ checkActiveIdentityExists(transactionId, restResponseWrapper, registrationTransaction,
+ verifyChallengeRequest);
+ break;
+ default:
+ throw new SignUpException(ErrorConstants.UNSUPPORTED_PURPOSE);
+ }
+ } catch (RestClientException e) {
+ log.error("Endpoint {} is unreachable.", getIdentityEndpoint);
+ throw new SignUpException(ErrorConstants.SERVER_UNREACHABLE);
}
}
@@ -426,6 +481,8 @@ private void saveIdentityData(RegisterRequest registerRequest, String transactio
identity.setFullName(userInfoMap.getFullName());
identity.setIDSchemaVersion(idSchemaVersion);
identity.setRegistrationType("L1");
+ identity.setPhoneVerified(true);
+ identity.setUpdatedAt(LocalDateTime.now(ZoneOffset.UTC).toEpochSecond(ZoneOffset.UTC));
String uin = getUniqueIdentifier(transactionId);
identity.setUIN(uin);
@@ -434,7 +491,7 @@ private void saveIdentityData(RegisterRequest registerRequest, String transactio
identity.setPassword(password);
//By default, phone is set as the selected handle.
- identity.setSelectedHandles(Arrays.asList("phone"));
+ identity.setSelectedHandles(List.of("phone"));
transaction.getHandlesStatus().put(getHandleRequestId(transaction.getApplicationId(),
"phone", userInfoMap.getPhone()), RegistrationStatus.PENDING);
@@ -445,6 +502,7 @@ private void saveIdentityData(RegisterRequest registerRequest, String transactio
addIdentity(identityRequest, transactionId);
}
+ @Timed(value = "addidentity.api.timer", percentiles = {0.9})
private void addIdentity(IdentityRequest identityRequest, String transactionId) throws SignUpException{
RestRequestWrapper restRequest = new RestRequestWrapper<>();
@@ -454,20 +512,26 @@ private void addIdentity(IdentityRequest identityRequest, String transactionId)
restRequest.setRequest(identityRequest);
log.debug("Transaction {} : start add identity", transactionId);
- HttpEntity> resReq = new HttpEntity<>(restRequest);
- RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(identityEndpoint,
- HttpMethod.POST,
- resReq,
- new ParameterizedTypeReference>() {}).getBody();
+ try {
+ HttpEntity> resReq = new HttpEntity<>(restRequest);
+ RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(identityEndpoint,
+ HttpMethod.POST,
+ resReq,
+ new ParameterizedTypeReference>() {
+ }).getBody();
+
+ if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
+ restResponseWrapper.getResponse().getStatus().equals("ACTIVATED")) {
+ return;
+ }
- if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
- restResponseWrapper.getResponse().getStatus().equals("ACTIVATED")) {
- return;
+ log.error("Transaction {} : Add identity failed with response {}", transactionId, restResponseWrapper);
+ throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
+ restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.ADD_IDENTITY_FAILED);
+ } catch (RestClientException e) {
+ log.error("Endpoint {} is unreachable.", identityEndpoint);
+ throw new SignUpException(ErrorConstants.SERVER_UNREACHABLE);
}
-
- log.error("Transaction {} : Add identity failed with response {}", transactionId, restResponseWrapper);
- throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
- restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.ADD_IDENTITY_FAILED);
}
private Password generateSaltedHash(String password, String transactionId) throws SignUpException{
@@ -478,37 +542,50 @@ private Password generateSaltedHash(String password, String transactionId) throw
HttpEntity> resReq = new HttpEntity<>(restRequestWrapper);
log.debug("Transaction {} : Generate salted hash started", transactionId);
- RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(generateHashEndpoint, HttpMethod.POST, resReq, new ParameterizedTypeReference>(){}).getBody();
+ try {
+ RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(
+ generateHashEndpoint, HttpMethod.POST, resReq, new ParameterizedTypeReference>(){}).getBody();
+
+ if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
+ !StringUtils.isEmpty(restResponseWrapper.getResponse().getHashValue()) &&
+ !StringUtils.isEmpty(restResponseWrapper.getResponse().getSalt())) {
+ return new Password(restResponseWrapper.getResponse().getHashValue(),
+ restResponseWrapper.getResponse().getSalt());
+ }
- if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
- !StringUtils.isEmpty(restResponseWrapper.getResponse().getHashValue()) &&
- !StringUtils.isEmpty(restResponseWrapper.getResponse().getSalt())) {
- return new Password(restResponseWrapper.getResponse().getHashValue(),
- restResponseWrapper.getResponse().getSalt());
+ log.error("Transaction {} : Generate salted hash failed with response {}", transactionId, restResponseWrapper);
+ throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
+ restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.HASH_GENERATE_FAILED);
+ } catch (RestClientException e) {
+ log.error("Endpoint {} is unreachable.", generateHashEndpoint);
+ throw new SignUpException(ErrorConstants.SERVER_UNREACHABLE);
}
-
- log.error("Transaction {} : Generate salted hash failed with response {}", transactionId, restResponseWrapper);
- throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
- restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.HASH_GENERATE_FAILED);
}
+ @Timed(value = "getuin.api.timer", percentiles = {0.9})
private String getUniqueIdentifier(String transactionId) throws SignUpException {
+ try {
+ RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(
+ getUinEndpoint,
+ HttpMethod.GET, null,
+ new ParameterizedTypeReference>() {}).getBody();
+
+ if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
+ !StringUtils.isEmpty(restResponseWrapper.getResponse().getUIN()) ) {
+ return restResponseWrapper.getResponse().getUIN();
+ }
- RestResponseWrapper restResponseWrapper = selfTokenRestTemplate.exchange(getUinEndpoint,
- HttpMethod.GET, null,
- new ParameterizedTypeReference>() {}).getBody();
-
- if (restResponseWrapper != null && restResponseWrapper.getResponse() != null &&
- !StringUtils.isEmpty(restResponseWrapper.getResponse().getUIN()) ) {
- return restResponseWrapper.getResponse().getUIN();
+ log.error("Transaction {} : Get unique identifier(UIN) failed with response {}", transactionId, restResponseWrapper);
+ throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
+ restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.GET_UIN_FAILED);
+ } catch (RestClientException e) {
+ log.error("Endpoint {} is unreachable.", getUinEndpoint);
+ throw new SignUpException(ErrorConstants.SERVER_UNREACHABLE);
}
-
- log.error("Transaction {} : Get unique identifier(UIN) failed with response {}", transactionId, restResponseWrapper);
- throw new SignUpException(restResponseWrapper != null && !CollectionUtils.isEmpty(restResponseWrapper.getErrors()) ?
- restResponseWrapper.getErrors().get(0).getErrorCode() : ErrorConstants.GET_UIN_FAILED);
}
- private void validateTransaction(RegistrationTransaction transaction, String identifier) {
+ private void validateTransaction(RegistrationTransaction transaction, String identifier,
+ GenerateChallengeRequest generateChallengeRequest) {
if(transaction == null) {
log.error("generate-challenge failed: validate transaction null");
throw new InvalidTransactionException();
@@ -528,24 +605,40 @@ private void validateTransaction(RegistrationTransaction transaction, String ide
log.error("generate-challenge failed: too early attempts");
throw new GenerateChallengeException(ErrorConstants.TOO_EARLY_ATTEMPT);
}
+
+ if(!transaction.getPurpose().equals(generateChallengeRequest.getPurpose())) {
+ log.error("generate-challenge failed: purpose mismatch");
+ throw new GenerateChallengeException(ErrorConstants.INVALID_PURPOSE);
+ }
}
+ @Timed(value = "getstatus.api.timer", percentiles = {0.9})
private RegistrationStatus getRegistrationStatusFromServer(String applicationId) {
- RestResponseWrapper