fineract-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nazeer1100...@apache.org
Subject fineract git commit: self service registration
Date Fri, 28 Jul 2017 14:28:35 GMT
Repository: fineract
Updated Branches:
  refs/heads/develop 0f98cbbed -> afdc665b5


self service registration


Project: http://git-wip-us.apache.org/repos/asf/fineract/repo
Commit: http://git-wip-us.apache.org/repos/asf/fineract/commit/afdc665b
Tree: http://git-wip-us.apache.org/repos/asf/fineract/tree/afdc665b
Diff: http://git-wip-us.apache.org/repos/asf/fineract/diff/afdc665b

Branch: refs/heads/develop
Commit: afdc665b52e599e7aa2c3f238c7e77528a63451b
Parents: 0f98cbb
Author: nazeer shaik <nazeer.shaik@confluxtechnologies.com>
Authored: Tue Jul 25 20:22:10 2017 +0530
Committer: nazeer shaik <nazeer.shaik@confluxtechnologies.com>
Committed: Tue Jul 25 20:22:10 2017 +0530

----------------------------------------------------------------------
 .../infrastructure/core/api/JsonCommand.java    |  23 ++
 .../client/domain/ClientRepository.java         |   8 +-
 .../client/domain/ClientRepositoryWrapper.java  |   9 +-
 .../exception/ClientNotFoundException.java      |   8 +
 .../registration/SelfServiceApiConstants.java   |  48 +++
 .../api/SelfServiceRegistrationApiResource.java |  68 +++++
 .../data/SelfServiceRegistrationData.java       |  70 +++++
 .../domain/SelfServiceRegistration.java         | 131 +++++++++
 .../SelfServiceRegistrationRepository.java      |  36 +++
 ...elfServiceRegistrationNotFoundException.java |  30 ++
 ...fServiceRegistrationReadPlatformService.java |  26 ++
 ...viceRegistrationReadPlatformServiceImpl.java |  50 ++++
 ...ServiceRegistrationWritePlatformService.java |  29 ++
 ...iceRegistrationWritePlatformServiceImpl.java | 293 +++++++++++++++++++
 .../service/AppUserReadPlatformService.java     |   2 +
 .../service/AppUserReadPlatformServiceImpl.java |   9 +
 .../META-INF/spring/securityContext.xml         |   4 +
 .../V332__self_service_registration_schema.sql  |  38 +++
 18 files changed, 880 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
index 9b8356d..76f30c6 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/api/JsonCommand.java
@@ -122,6 +122,29 @@ public final class JsonCommand {
         this.organisationCreditBureauId=organisationCreditBureauId;
     }
     
+    public static JsonCommand fromJsonElement(final Long resourceId, final JsonElement parsedCommand) {
+        return new JsonCommand(resourceId, parsedCommand);
+    }
+    
+    public JsonCommand(final Long resourceId, final JsonElement parsedCommand) {
+        this.parsedCommand = parsedCommand;
+        this.resourceId = resourceId;
+        this.commandId = null;
+        this.jsonCommand = null;        
+        this.fromApiJsonHelper = null;
+        this.entityName = null;
+        this.subresourceId = null;
+        this.groupId = null;
+        this.clientId = null;
+        this.loanId = null;
+        this.savingsId = null;
+        this.transactionId = null;
+        this.url = null;
+        this.productId = null;
+        this.creditBureauId=null;
+        this.organisationCreditBureauId=null;
+    }
+    
     public Long getOrganisationCreditBureauId() {
         return this.organisationCreditBureauId;
     }

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java
index e718265..eb2714c 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepository.java
@@ -20,7 +20,13 @@ package org.apache.fineract.portfolio.client.domain;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
 
 abstract interface ClientRepository extends JpaRepository<Client, Long>, JpaSpecificationExecutor<Client> {
-    // no added behaviour
+    
+    public static final String FIND_CLIENT_BY_ACCOUNT_NUMBER = "select client from Client client where client.accountNumber = :accountNumber";
+
+    @Query(FIND_CLIENT_BY_ACCOUNT_NUMBER)
+    Client getClientByAccountNumber(@Param("accountNumber") String accountNumber);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepositoryWrapper.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepositoryWrapper.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepositoryWrapper.java
index f4231d1..b3e8e9e 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepositoryWrapper.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/domain/ClientRepositoryWrapper.java
@@ -85,5 +85,12 @@ public class ClientRepositoryWrapper {
         this.context.validateAccessRights(client.getOffice().getHierarchy());
         return client;
     }
-
+    
+    public Client getClientByAccountNumber(String accountNumber){
+        Client client = this.repository.getClientByAccountNumber(accountNumber);
+        if(client==null){
+            throw  new ClientNotFoundException(accountNumber);
+        }
+        return client;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/exception/ClientNotFoundException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/exception/ClientNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/exception/ClientNotFoundException.java
index 7a6f034..1c182d4 100644
--- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/exception/ClientNotFoundException.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/exception/ClientNotFoundException.java
@@ -28,4 +28,12 @@ public class ClientNotFoundException extends AbstractPlatformResourceNotFoundExc
     public ClientNotFoundException(final Long id) {
         super("error.msg.client.id.invalid", "Client with identifier " + id + " does not exist", id);
     }
+    
+    public ClientNotFoundException() {
+        super("error.msg.client.not.found.with.basic.details", "Client not found with basic details.");
+    }
+    
+    public ClientNotFoundException(String accountNumber) {
+        super("error.msg.client.not.found.with.account.number", "Client not found with account number "+accountNumber+".");
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/SelfServiceApiConstants.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/SelfServiceApiConstants.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/SelfServiceApiConstants.java
new file mode 100644
index 0000000..2362523
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/SelfServiceApiConstants.java
@@ -0,0 +1,48 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SelfServiceApiConstants {
+
+    public static final String accountNumberParamName = "accountNumber";
+    public static final String passwordParamName = "password";
+    public static final String firstNameParamName = "firstName";
+    public static final String mobileNumberParamName = "mobileNumber";
+    public static final String lastNameParamName = "lastName";
+    public static final String emailParamName = "email";
+    public static final String usernameParamName = "username";
+    public static final String authenticationTokenParamName = "authenticationToken";
+    public static final String authenticationModeParamName = "authenticationMode";
+    public static final String emailModeParamName = "email";
+    public static final String mobileModeParamName = "mobile";
+    public static final String requestIdParamName = "requestId";
+    public static final String createRequestSuccessMessage = "Self service request created.";
+    public static final Set<String> REGISTRATION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(usernameParamName,
+            accountNumberParamName, passwordParamName, firstNameParamName, mobileNumberParamName, lastNameParamName, emailParamName,
+            authenticationModeParamName));
+    public static final Set<String> CREATE_USER_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(requestIdParamName,
+            authenticationTokenParamName));
+    public static final Object[] SUPPORTED_AUTHENTICATION_MODE_PARAMETERS = new Object[] {emailModeParamName,
+            mobileModeParamName};
+    
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java
new file mode 100644
index 0000000..64dcfa9
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.fineract.portfolio.self.registration.api;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
+import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import org.apache.fineract.portfolio.note.data.NoteData;
+import org.apache.fineract.portfolio.self.registration.SelfServiceApiConstants;
+import org.apache.fineract.portfolio.self.registration.service.SelfServiceRegistrationWritePlatformService;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Component;
+
+@Path("/self/registration")
+@Component
+@Scope("singleton")
+public class SelfServiceRegistrationApiResource {
+
+    private final SelfServiceRegistrationWritePlatformService selfServiceRegistrationWritePlatformService;
+    private final DefaultToApiJsonSerializer<AppUser> toApiJsonSerializer;
+
+    @Autowired
+    public SelfServiceRegistrationApiResource(
+            final SelfServiceRegistrationWritePlatformService selfServiceRegistrationWritePlatformService,
+            final DefaultToApiJsonSerializer<AppUser> toApiJsonSerializer) {
+        this.selfServiceRegistrationWritePlatformService = selfServiceRegistrationWritePlatformService;
+        this.toApiJsonSerializer = toApiJsonSerializer;
+    }
+
+    @POST
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String createSelfServiceRegistrationRequest(final String apiRequestBodyAsJson) {
+        this.selfServiceRegistrationWritePlatformService.createRegistrationRequest(apiRequestBodyAsJson);
+        return SelfServiceApiConstants.createRequestSuccessMessage;
+    }
+
+    @POST
+    @Path("user")
+    @Produces({ MediaType.APPLICATION_JSON })
+    public String createSelfServiceUser(final String apiRequestBodyAsJson) {
+        AppUser user = this.selfServiceRegistrationWritePlatformService.createUser(apiRequestBodyAsJson);
+        return this.toApiJsonSerializer.serialize(CommandProcessingResult.resourceResult(user.getId(), null));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/data/SelfServiceRegistrationData.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/data/SelfServiceRegistrationData.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/data/SelfServiceRegistrationData.java
new file mode 100644
index 0000000..9f62500
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/data/SelfServiceRegistrationData.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.data;
+
+import org.apache.fineract.portfolio.client.domain.Client;
+import org.joda.time.LocalDate;
+
+public class SelfServiceRegistrationData {
+
+    @SuppressWarnings("unused")
+    private final Long id;
+    @SuppressWarnings("unused")
+    private Client client;
+    @SuppressWarnings("unused")
+    private String firstName;
+    @SuppressWarnings("unused")
+    private String lastName;
+    @SuppressWarnings("unused")
+    private String mobileNumber;
+    @SuppressWarnings("unused")
+    private String email;
+    @SuppressWarnings("unused")
+    private String authenticationToken;
+    @SuppressWarnings("unused")
+    private String username;
+    @SuppressWarnings("unused")
+    private String password;
+    @SuppressWarnings("unused")
+    private LocalDate createdDate;
+
+    public SelfServiceRegistrationData(final Long id, final Client client, final String firstName, final String lastName,
+            final String mobileNumber, final String email, final String authenticationToken, final String username, final String password,
+            final LocalDate createdDate) {
+        this.id = id;
+        this.client = client;
+        this.firstName = firstName;
+        this.lastName = lastName;
+        this.mobileNumber = mobileNumber;
+        this.email = email;
+        this.authenticationToken = authenticationToken;
+        this.username = username;
+        this.password = password;
+        this.createdDate = createdDate;
+    }
+
+    public static SelfServiceRegistrationData getData(final Long id, final Client client, final String firstName, final String lastName,
+            final String mobileNumber, final String email, final String authenticationToken, final String username, final String password,
+            final LocalDate createdDate) {
+        return new SelfServiceRegistrationData(id, client, firstName, lastName, mobileNumber, email, authenticationToken, username,
+                password, createdDate);
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistration.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistration.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistration.java
new file mode 100644
index 0000000..7c226c5
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistration.java
@@ -0,0 +1,131 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.domain;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
+import org.apache.fineract.portfolio.client.domain.Client;
+
+@Entity
+@Table(name = "request_audit_table")
+public class SelfServiceRegistration extends AbstractPersistableCustom<Long> {
+
+    @ManyToOne
+    @JoinColumn(name = "client_id", nullable = false)
+    private Client client;
+
+    @Column(name = "account_number", length = 100, nullable = false)
+    private String accountNumber;
+
+    @Column(name = "firstname", length = 100, nullable = false)
+    private String firstName;
+
+    @Column(name = "lastname", length = 100, nullable = false)
+    private String lastName;
+
+    @Column(name = "mobile_number", length = 50, nullable = true)
+    private String mobileNumber;
+
+    @Column(name = "email", length = 100, nullable = false)
+    private String email;
+
+    @Column(name = "authentication_token", length = 100, nullable = true)
+    private String authenticationToken;
+
+    @Column(name = "username", length = 100, nullable = false)
+    private String username;
+
+    @Column(name = "password", length = 100, nullable = false)
+    private String password;
+
+    @Column(name = "created_date", nullable = false)
+    @Temporal(TemporalType.DATE)
+    private Date createdDate;
+
+    public SelfServiceRegistration(final Client client, String accountNumber, final String firstName, final String lastName,
+            final String mobileNumber, final String email, final String authenticationToken, final String username, final String password) {
+        this.client = client;
+        this.accountNumber = accountNumber;
+        this.firstName = firstName;
+        this.lastName = lastName;
+        this.mobileNumber = mobileNumber;
+        this.email = email;
+        this.authenticationToken = authenticationToken;
+        this.username = username;
+        this.password = password;
+        this.createdDate = new Date();
+    }
+
+    public static SelfServiceRegistration instance(final Client client, final String accountNumber, final String firstname,
+            final String lastName, final String mobileNumber, final String email, final String authenticationToken, final String username,
+            final String password) {
+        return new SelfServiceRegistration(client, accountNumber, firstname, lastName, mobileNumber, email, authenticationToken, username,
+                password);
+    }
+
+    public Client getClient() {
+        return this.client;
+    }
+
+    public String getFirstName() {
+        return this.firstName;
+    }
+
+    public String getLastName() {
+        return this.lastName;
+    }
+
+    public String getMobileNumber() {
+        return this.mobileNumber;
+    }
+
+    public String getEmail() {
+        return this.email;
+    }
+
+    public String getAuthenticationToken() {
+        return this.authenticationToken;
+    }
+
+    public Date getCreatedDate() {
+        return this.createdDate;
+    }
+
+    public String getUsername() {
+        return this.username;
+    }
+
+    public String getPassword() {
+        return this.password;
+    }
+
+    public String getAccountNumber() {
+        return this.accountNumber;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistrationRepository.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistrationRepository.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistrationRepository.java
new file mode 100644
index 0000000..2f93482
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/domain/SelfServiceRegistrationRepository.java
@@ -0,0 +1,36 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.domain;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+public interface SelfServiceRegistrationRepository extends JpaRepository<SelfServiceRegistration, Long>,
+        JpaSpecificationExecutor<SelfServiceRegistration> {
+
+    public static final String FIND_BY_REQUEST_AND_AUTHENTICATION_TOKEN = "select request from SelfServiceRegistration request where request.id = :id and "
+            + "request.authenticationToken = :authenticationToken";
+
+    @Query(FIND_BY_REQUEST_AND_AUTHENTICATION_TOKEN)
+    SelfServiceRegistration getRequestByIdAndAuthenticationToken(@Param("id") Long id,
+            @Param("authenticationToken") String authenticationToken);
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/exception/SelfServiceRegistrationNotFoundException.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/exception/SelfServiceRegistrationNotFoundException.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/exception/SelfServiceRegistrationNotFoundException.java
new file mode 100644
index 0000000..888a827
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/exception/SelfServiceRegistrationNotFoundException.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.exception;
+
+import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
+
+public class SelfServiceRegistrationNotFoundException extends AbstractPlatformResourceNotFoundException {
+
+    public SelfServiceRegistrationNotFoundException(Long requestId, String authenticationToken) {
+        super("error.msg.self.service.registration.not.found", "Self service registration not found with request id : " + requestId
+                + " and authentication token :" + authenticationToken);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformService.java
new file mode 100644
index 0000000..9ff45b4
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformService.java
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.service;
+
+public interface SelfServiceRegistrationReadPlatformService {
+
+    public boolean isClientExist(String accountNumber, String firstName, String lastName, String mobileNumber,
+            boolean isEmailAuthenticationMode);
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformServiceImpl.java
new file mode 100644
index 0000000..ce265e6
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationReadPlatformServiceImpl.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.service;
+
+import org.apache.fineract.infrastructure.core.service.RoutingDataSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+@Service
+public class SelfServiceRegistrationReadPlatformServiceImpl implements SelfServiceRegistrationReadPlatformService {
+
+    private final JdbcTemplate jdbcTemplate;
+
+    @Autowired
+    public SelfServiceRegistrationReadPlatformServiceImpl(final RoutingDataSource dataSource) {
+        this.jdbcTemplate = new JdbcTemplate(dataSource);
+    }
+
+    @Override
+    public boolean isClientExist(String accountNumber, String firstName, String lastName, String mobileNumber,
+            boolean isEmailAuthenticationMode) {
+        String sql = "select count(*) from m_client where account_no = ? and firstname = ? and lastname = ?";
+        Object[] params = new Object[] { accountNumber, firstName, lastName };
+        if (!isEmailAuthenticationMode) {
+            sql = sql + " and mobile_no = ?";
+            params = new Object[] { accountNumber, firstName, lastName, mobileNumber };
+        }
+        Integer count = this.jdbcTemplate.queryForObject(sql, params, Integer.class);
+        if (count == 0) { return false; }
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformService.java
new file mode 100644
index 0000000..7827c44
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformService.java
@@ -0,0 +1,29 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.service;
+
+import org.apache.fineract.portfolio.self.registration.domain.SelfServiceRegistration;
+import org.apache.fineract.useradministration.domain.AppUser;
+
+public interface SelfServiceRegistrationWritePlatformService {
+
+    public SelfServiceRegistration createRegistrationRequest(String apiRequestBodyAsJson);
+
+    public AppUser createUser(String apiRequestBodyAsJson);
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformServiceImpl.java
new file mode 100644
index 0000000..7797b2f
--- /dev/null
+++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/service/SelfServiceRegistrationWritePlatformServiceImpl.java
@@ -0,0 +1,293 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.registration.service;
+
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.PersistenceException;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.fineract.infrastructure.campaigns.sms.data.SmsProviderData;
+import org.apache.fineract.infrastructure.campaigns.sms.domain.SmsCampaign;
+import org.apache.fineract.infrastructure.campaigns.sms.service.SmsCampaignDropdownReadPlatformService;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.data.ApiParameterError;
+import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
+import org.apache.fineract.infrastructure.core.domain.EmailDetail;
+import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
+import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.core.service.GmailBackedPlatformEmailService;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessage;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessageRepository;
+import org.apache.fineract.infrastructure.sms.domain.SmsMessageStatusType;
+import org.apache.fineract.infrastructure.sms.scheduler.SmsMessageScheduledJobService;
+import org.apache.fineract.organisation.staff.domain.Staff;
+import org.apache.fineract.portfolio.client.domain.Client;
+import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
+import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
+import org.apache.fineract.portfolio.group.domain.Group;
+import org.apache.fineract.portfolio.self.registration.SelfServiceApiConstants;
+import org.apache.fineract.portfolio.self.registration.domain.SelfServiceRegistration;
+import org.apache.fineract.portfolio.self.registration.domain.SelfServiceRegistrationRepository;
+import org.apache.fineract.portfolio.self.registration.exception.SelfServiceRegistrationNotFoundException;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.apache.fineract.useradministration.domain.PasswordValidationPolicy;
+import org.apache.fineract.useradministration.domain.PasswordValidationPolicyRepository;
+import org.apache.fineract.useradministration.domain.Role;
+import org.apache.fineract.useradministration.domain.UserDomainService;
+import org.apache.fineract.useradministration.service.AppUserReadPlatformService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.security.authentication.AuthenticationServiceException;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Service;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.reflect.TypeToken;
+
+@Service
+public class SelfServiceRegistrationWritePlatformServiceImpl implements SelfServiceRegistrationWritePlatformService {
+
+    private final SelfServiceRegistrationRepository selfServiceRegistrationRepository;
+    private final FromJsonHelper fromApiJsonHelper;
+    private final SelfServiceRegistrationReadPlatformService selfServiceRegistrationReadPlatformService;
+    private final ClientRepositoryWrapper clientRepository;
+    private final PasswordValidationPolicyRepository passwordValidationPolicy;
+    private final UserDomainService userDomainService;
+    private final GmailBackedPlatformEmailService gmailBackedPlatformEmailService;
+    private final SmsMessageRepository smsMessageRepository;
+    private SmsMessageScheduledJobService smsMessageScheduledJobService;
+    private final SmsCampaignDropdownReadPlatformService smsCampaignDropdownReadPlatformService;
+    private final AppUserReadPlatformService appUserReadPlatformService;
+
+    @Autowired
+    public SelfServiceRegistrationWritePlatformServiceImpl(final SelfServiceRegistrationRepository selfServiceRegistrationRepository,
+            final FromJsonHelper fromApiJsonHelper,
+            final SelfServiceRegistrationReadPlatformService selfServiceRegistrationReadPlatformService,
+            final ClientRepositoryWrapper clientRepository, final PasswordValidationPolicyRepository passwordValidationPolicy,
+            final UserDomainService userDomainService, final GmailBackedPlatformEmailService gmailBackedPlatformEmailService,
+            final SmsMessageRepository smsMessageRepository, SmsMessageScheduledJobService smsMessageScheduledJobService,
+            final SmsCampaignDropdownReadPlatformService smsCampaignDropdownReadPlatformService,
+            final AppUserReadPlatformService appUserReadPlatformService) {
+        this.selfServiceRegistrationRepository = selfServiceRegistrationRepository;
+        this.fromApiJsonHelper = fromApiJsonHelper;
+        this.selfServiceRegistrationReadPlatformService = selfServiceRegistrationReadPlatformService;
+        this.clientRepository = clientRepository;
+        this.passwordValidationPolicy = passwordValidationPolicy;
+        this.userDomainService = userDomainService;
+        this.gmailBackedPlatformEmailService = gmailBackedPlatformEmailService;
+        this.smsMessageRepository = smsMessageRepository;
+        this.smsMessageScheduledJobService = smsMessageScheduledJobService;
+        this.smsCampaignDropdownReadPlatformService = smsCampaignDropdownReadPlatformService;
+        this.appUserReadPlatformService = appUserReadPlatformService;
+    }
+
+    @Override
+    public SelfServiceRegistration createRegistrationRequest(String apiRequestBodyAsJson) {
+        Gson gson = new Gson();
+        final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
+        final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+        final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("user");
+        this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, apiRequestBodyAsJson,
+                SelfServiceApiConstants.REGISTRATION_REQUEST_DATA_PARAMETERS);
+        JsonElement element = gson.fromJson(apiRequestBodyAsJson.toString(), JsonElement.class);
+
+        String accountNumber = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.accountNumberParamName, element);
+        baseDataValidator.reset().parameter(SelfServiceApiConstants.accountNumberParamName).value(accountNumber).notNull().notBlank()
+                .notExceedingLengthOf(100);
+
+        String firstName = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.firstNameParamName, element);
+        baseDataValidator.reset().parameter(SelfServiceApiConstants.firstNameParamName).value(firstName).notBlank()
+                .notExceedingLengthOf(100);
+
+        String lastName = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.lastNameParamName, element);
+        baseDataValidator.reset().parameter(SelfServiceApiConstants.lastNameParamName).value(lastName).notBlank().notExceedingLengthOf(100);
+
+        String username = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.usernameParamName, element);
+        baseDataValidator.reset().parameter(SelfServiceApiConstants.usernameParamName).value(username).notBlank().notExceedingLengthOf(100);
+
+        // validate password policy
+        String password = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.passwordParamName, element);
+        final PasswordValidationPolicy validationPolicy = this.passwordValidationPolicy.findActivePasswordValidationPolicy();
+        final String regex = validationPolicy.getRegex();
+        final String description = validationPolicy.getDescription();
+        baseDataValidator.reset().parameter(SelfServiceApiConstants.passwordParamName).value(password)
+                .matchesRegularExpression(regex, description).notExceedingLengthOf(100);
+
+        String authenticationMode = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.authenticationModeParamName, element);
+        baseDataValidator.reset().parameter(SelfServiceApiConstants.authenticationModeParamName).value(authenticationMode).notBlank()
+                .isOneOfTheseStringValues(SelfServiceApiConstants.emailModeParamName, SelfServiceApiConstants.mobileModeParamName);
+
+        String email = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.emailParamName, element);
+        baseDataValidator.reset().parameter(SelfServiceApiConstants.emailParamName).value(email).notNull().notBlank()
+                .notExceedingLengthOf(100);
+
+        boolean isEmailAuthenticationMode = authenticationMode.equalsIgnoreCase(SelfServiceApiConstants.emailModeParamName);
+        String mobileNumber = null;
+        if (!isEmailAuthenticationMode) {
+            mobileNumber = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.mobileNumberParamName, element);
+            baseDataValidator.reset().parameter(SelfServiceApiConstants.mobileNumberParamName).value(mobileNumber).notNull()
+                    .validatePhoneNumber();
+        }
+        validateForDuplicateUsername(username);
+
+        throwExceptionIfValidationError(dataValidationErrors, accountNumber, firstName, lastName, mobileNumber, isEmailAuthenticationMode);
+
+        String authenticationToken = randomAuthorizationTokenGeneration();
+        Client client = this.clientRepository.getClientByAccountNumber(accountNumber);
+        SelfServiceRegistration selfServiceRegistration = SelfServiceRegistration.instance(client, accountNumber, firstName, lastName,
+                mobileNumber, email, authenticationToken, username, password);
+        this.selfServiceRegistrationRepository.saveAndFlush(selfServiceRegistration);
+        sendAuthorizationToken(selfServiceRegistration, isEmailAuthenticationMode);
+        return selfServiceRegistration;
+
+    }
+
+    public void validateForDuplicateUsername(String username) {
+        boolean isDuplicateUserName = this.appUserReadPlatformService.isUsernameExist(username);
+        if (isDuplicateUserName) {
+            final StringBuilder defaultMessageBuilder = new StringBuilder("User with username ").append(username)
+                    .append(" already exists.");
+            throw new PlatformDataIntegrityException("error.msg.user.duplicate.username", defaultMessageBuilder.toString(),
+                    SelfServiceApiConstants.usernameParamName, username);
+        }
+    }
+
+    public void sendAuthorizationToken(SelfServiceRegistration selfServiceRegistration, Boolean isEmailAuthenticationMode) {
+        if (isEmailAuthenticationMode) {
+            sendAuthorizationMail(selfServiceRegistration);
+        } else {
+            sendAuthorizationMessage(selfServiceRegistration);
+        }
+    }
+
+    private void sendAuthorizationMessage(SelfServiceRegistration selfServiceRegistration) {
+        Collection<SmsProviderData> smsProviders = this.smsCampaignDropdownReadPlatformService.retrieveSmsProviders();
+        if (smsProviders.isEmpty()) { throw new PlatformDataIntegrityException("error.msg.mobile.service.provider.not.available",
+                "Mobile service provider not available."); }
+        Long providerId = (new ArrayList<>(smsProviders)).get(0).getId();
+        final String message = "Hi  " + selfServiceRegistration.getFirstName() + "," + "\n"
+                + "To create user, please use following details \n" + "Request Id : " + selfServiceRegistration.getId()
+                + "\n Authentication Token : " + selfServiceRegistration.getAuthenticationToken();
+        String externalId = null;
+        Group group = null;
+        Staff staff = null;
+        SmsCampaign smsCampaign = null;
+        SmsMessage smsMessage = SmsMessage.instance(externalId, group, selfServiceRegistration.getClient(), staff,
+                SmsMessageStatusType.PENDING, message, selfServiceRegistration.getMobileNumber(), smsCampaign);
+        this.smsMessageRepository.save(smsMessage);
+        this.smsMessageScheduledJobService.sendTriggeredMessage(new ArrayList<>(Arrays.asList(smsMessage)), providerId);
+    }
+
+    private void sendAuthorizationMail(SelfServiceRegistration selfServiceRegistration) {
+        final String subject = "Authorization token ";
+        final String body = "Hi  " + selfServiceRegistration.getFirstName() + "," + "\n" + "To create user, please use following details\n"
+                + "Request Id : " + selfServiceRegistration.getId() + "\n Authentication Token : "
+                + selfServiceRegistration.getAuthenticationToken();
+
+        final EmailDetail emailDetail = new EmailDetail(subject, body, selfServiceRegistration.getEmail(),
+                selfServiceRegistration.getFirstName());
+        this.gmailBackedPlatformEmailService.sendDefinedEmail(emailDetail);
+    }
+
+    private void throwExceptionIfValidationError(final List<ApiParameterError> dataValidationErrors, String accountNumber,
+            String firstName, String lastName, String mobileNumber, boolean isEmailAuthenticationMode) {
+        if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+        boolean isClientExist = this.selfServiceRegistrationReadPlatformService.isClientExist(accountNumber, firstName, lastName,
+                mobileNumber, isEmailAuthenticationMode);
+        if (!isClientExist) { throw new ClientNotFoundException(); }
+    }
+
+    public static String randomAuthorizationTokenGeneration() {
+        Integer randomPIN = (int) (Math.random() * 9000) + 1000;
+        return randomPIN.toString();
+    }
+
+    @Override
+    public AppUser createUser(String apiRequestBodyAsJson) {
+        JsonCommand command = null;
+        String username = null;
+        try {
+            Gson gson = new Gson();
+            final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
+            final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
+            final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("user");
+            this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, apiRequestBodyAsJson,
+                    SelfServiceApiConstants.CREATE_USER_REQUEST_DATA_PARAMETERS);
+            JsonElement element = gson.fromJson(apiRequestBodyAsJson.toString(), JsonElement.class);
+
+            Long id = this.fromApiJsonHelper.extractLongNamed(SelfServiceApiConstants.requestIdParamName, element);
+            baseDataValidator.reset().parameter(SelfServiceApiConstants.requestIdParamName).value(id).notNull().integerGreaterThanZero();
+            command = JsonCommand.fromJsonElement(id, element);
+            String authenticationToken = this.fromApiJsonHelper.extractStringNamed(SelfServiceApiConstants.authenticationTokenParamName,
+                    element);
+            baseDataValidator.reset().parameter(SelfServiceApiConstants.authenticationTokenParamName).value(authenticationToken).notBlank()
+                    .notNull().notExceedingLengthOf(100);
+
+            if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException(dataValidationErrors); }
+
+            SelfServiceRegistration selfServiceRegistration = this.selfServiceRegistrationRepository.getRequestByIdAndAuthenticationToken(
+                    id, authenticationToken);
+            if (selfServiceRegistration == null) { throw new SelfServiceRegistrationNotFoundException(id, authenticationToken); }
+            username = selfServiceRegistration.getUsername();
+            Client client = selfServiceRegistration.getClient();
+            final boolean passwordNeverExpire = true;
+            final boolean isSelfServiceUser = true;
+            final Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
+            authorities.add(new SimpleGrantedAuthority("DUMMY_ROLE_NOT_USED_OR_PERSISTED_TO_AVOID_EXCEPTION"));
+            final Set<Role> allRoles = new HashSet<>();
+            List<Client> clients = new ArrayList<>(Arrays.asList(client));
+            User user = new User(selfServiceRegistration.getUsername(), selfServiceRegistration.getPassword(), authorities);
+            AppUser appUser = new AppUser(client.getOffice(), user, allRoles, selfServiceRegistration.getEmail(), client.getFirstname(),
+                    client.getLastname(), null, passwordNeverExpire, isSelfServiceUser, clients);
+            this.userDomainService.create(appUser, true);
+            return appUser;
+
+        } catch (final DataIntegrityViolationException dve) {
+            handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve, username);
+            return null;
+        } catch (final PersistenceException | AuthenticationServiceException dve) {
+            Throwable throwable = ExceptionUtils.getRootCause(dve.getCause());
+            handleDataIntegrityIssues(command, throwable, dve, username);
+            return null;
+        }
+
+    }
+
+    private void handleDataIntegrityIssues(final JsonCommand command, final Throwable realCause, final Exception dve, String username) {
+        if (realCause.getMessage().contains("'username_org'")) {
+            final StringBuilder defaultMessageBuilder = new StringBuilder("User with username ").append(username)
+                    .append(" already exists.");
+            throw new PlatformDataIntegrityException("error.msg.user.duplicate.username", defaultMessageBuilder.toString(), "username",
+                    username);
+        }
+        throw new PlatformDataIntegrityException("error.msg.unknown.data.integrity.issue", "Unknown data integrity issue with resource.");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java
index 067c725..b17f6a1 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformService.java
@@ -31,4 +31,6 @@ public interface AppUserReadPlatformService {
     AppUserData retrieveNewUserDetails();
 
     AppUserData retrieveUser(Long userId);
+    
+    boolean isUsernameExist(String username);
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java
index 21e064f..13cbbd8 100755
--- a/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java
+++ b/fineract-provider/src/main/java/org/apache/fineract/useradministration/service/AppUserReadPlatformServiceImpl.java
@@ -212,4 +212,13 @@ public class AppUserReadPlatformServiceImpl implements AppUserReadPlatformServic
                     + " join m_office o on o.id = u.office_id where o.hierarchy like ? and u.is_deleted=0 order by u.username";
         }
     }
+
+    @Override
+    public boolean isUsernameExist(String username) {
+        String sql = "select count(*) from m_appuser where username = ?";
+        Object[] params = new Object[] { username };
+        Integer count = this.jdbcTemplate.queryForObject(sql, params, Integer.class);
+        if (count == 0) { return false; }
+        return true;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/resources/META-INF/spring/securityContext.xml
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/resources/META-INF/spring/securityContext.xml b/fineract-provider/src/main/resources/META-INF/spring/securityContext.xml
index ee4fb6d..f03220f 100644
--- a/fineract-provider/src/main/resources/META-INF/spring/securityContext.xml
+++ b/fineract-provider/src/main/resources/META-INF/spring/securityContext.xml
@@ -38,6 +38,10 @@
 				method="POST" requires-channel="https" />
 			<intercept-url pattern="/api/*/self/authentication" access="permitAll"
 				method="POST" requires-channel="https" />
+			<intercept-url pattern="/api/*/self/registration" access="permitAll"
+				method="POST" requires-channel="https" />
+			<intercept-url pattern="/api/*/self/registration/user" access="permitAll"
+				method="POST" requires-channel="https" />
 			<intercept-url pattern="/api/**" access="isFullyAuthenticated()"
 				method="GET" requires-channel="https" />
 			<intercept-url pattern="/api/**" access="isFullyAuthenticated()"

http://git-wip-us.apache.org/repos/asf/fineract/blob/afdc665b/fineract-provider/src/main/resources/sql/migrations/core_db/V332__self_service_registration_schema.sql
----------------------------------------------------------------------
diff --git a/fineract-provider/src/main/resources/sql/migrations/core_db/V332__self_service_registration_schema.sql b/fineract-provider/src/main/resources/sql/migrations/core_db/V332__self_service_registration_schema.sql
new file mode 100644
index 0000000..0f93700
--- /dev/null
+++ b/fineract-provider/src/main/resources/sql/migrations/core_db/V332__self_service_registration_schema.sql
@@ -0,0 +1,38 @@
+--
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements. See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership. The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License. You may obtain a copy of the License at
+--
+-- http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied. See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+--
+
+CREATE TABLE `request_audit_table` (
+	`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
+	`lastname` VARCHAR(100) NOT NULL,
+	`username` VARCHAR(100) NOT NULL,
+	`mobile_number` VARCHAR(50) NULL DEFAULT NULL,
+	`firstname` VARCHAR(100) NOT NULL,
+	`authentication_token` VARCHAR(100) NULL DEFAULT NULL,
+	`password` VARCHAR(250) NOT NULL,
+	`email` VARCHAR(100) NOT NULL,
+	`client_id` BIGINT(20) NOT NULL,
+	`created_date` DATE NOT NULL,
+	`account_number` VARCHAR(100) NOT NULL,
+	PRIMARY KEY (`id`),
+	INDEX `FK1_request_audit_table_m_client` (`client_id`),
+	CONSTRAINT `FK1_request_audit_table_m_client` FOREIGN KEY (`client_id`) REFERENCES `m_client` (`id`)
+)
+COLLATE='utf8_general_ci'
+ENGINE=InnoDB
+;


Mime
View raw message