irods-contrib / metalnx-web

Metalnx Web Application
https://metalnx.github.io/
BSD 3-Clause "New" or "Revised" License
36 stars 36 forks source link

Manual Registration Page on metalnx 2.2.0 #221

Closed NhlamuloChauke closed 3 years ago

NhlamuloChauke commented 3 years ago

Hi I am trying to create a manual registration form for metalnx, I am getting the following error below when adding the user.

attrib:org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.irodsServices' defined in URL [jar:file:/usr/local/tomcat/webapps/metalnx/WEB-INF/lib/emc-metalnx-services-4.3.2.1-SNAPSHOT.jar!/com/emc/metalnx/services/irods/IRODSServicesImpl.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.emc.metalnx.services.irods.IRODSServicesImpl]: Constructor threw exception; nested exception is java.lang.ClassCastException: class org.springframework.security.web.authentication.WebAuthenticationDetails cannot be cast to class com.emc.metalnx.services.auth.UserTokenDetails (org.springframework.security.web.authentication.WebAuthenticationDetails and com.emc.metalnx.services.auth.UserTokenDetails are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @14a54ef6)

This is the controller code and page below. Your response will be highly appreciated.

Page

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"/>

<script>
   //function To Disable Submit Button | Terms and Condition Agreement
   function disableSubmit() {
      document.getElementById("submitUserFormBtn").disabled = true;
     }
   //function To Activate Submit Button | Terms and Condition Agreement
   function activateButton(element) {
    if(element.checked) { 
        document.getElementById("submitUserFormBtn").disabled = false;
    }
    else {
        document.getElementById("submitUserFormBtn").disabled = true;
         }
      }

   function checkPasswordMatch() {
       var password = $("#inputPassword").val();
       var confirmPassword = $("#inputPasswordConfirmation").val();
       if (password != confirmPassword)
            $("#CheckPasswordMatch").html("Passwords does not match!");
       else
            $("#CheckPasswordMatch").html("Passwords match.");
    }
    $(document).ready(function () {
       $("#txtConfirmPassword").keyup(checkPasswordMatch);
    });

</script>

<title>Registration</title>
</head>
<body onload="disableSubmit()" >
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed"
                    data-toggle="collapse" data-target="#navbar" aria-expanded="false"
                    aria-controls="navbar">
                    <span class="sr-only">Toggle navigation</span> <span
                        class="icon-bar"></span> <span class="icon-bar"></span> <span
                        class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="#">Data Deposit Tool</a>
            </div>
        </div>
    </nav>

    <br/>
    <br/>

    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">

                <div th:if="${param.success}">
                    <div class="alert alert-info">You have Successfully Registered
                        To Data Deposit Tool</div>
                </div>
                <h1>Registration</h1>
                <form th:action="@{${requestMapping}}" th:object="${user}" method="POST">

                <!--
                    <div class="form-group">
                        <label for="firstName" class="control-label">First Name</label>: 
                        <input type="text" id="inputFirstName" class="form-control" th:field="*{firstName}" 
                        placeholder="FirstName" th:required="required"/>
                    </div>
                    <div class="form-group">
                        <label for="lastName" class="control-label">Last Name</label>: 
                        <input type="text" id="inputLastName" class="form-control" th:field="*{lastName}"
                        placeholder="LastName" th:required="required" />
                    </div>
                    -->

                    <div class="form-group">
                        <label for="username" class="control-label">Username</label>: 
                        <input type="text" id="inputUsername" class="form-control" th:field="*{username}" 
                        placeholder="Username" />
                    </div>

                <!--<
                    <div class="form-group">
                        <label for="email" class="control-label">Email Address</label>: 
                        <input type="email" id="email" class="form-control" th:field="*{email}" 
                        placeholder="Email Address" th:required="required"/>
                    </div>

                    <div class="form-group">
                        <label for="department" class="control-label">Institution</label>:
                        <input type="text" id="inputDepartment" class="form-control" 
                        th:field="*{department}" placeholder="Institution" th:required="required"/>
                    </div>-->

                    <div class="form-group">
                        <label for="password" class="control-label">Password</label>: 
                        <input id="inputPassword" class="form-control" type="password" th:field="*{password}" 
                        placeholder="Password" th:required="required"/>
                    </div>
                    <div class="form-group">
                        <label for="confirmPassword" class="control-label">Confirm
                            Password</label>: 
                            <input id="inputPasswordConfirmation" class="form-control"
                            type="password"
                            placeholder="Password" th:required="required"/>
                    </div>

                    <div class="form-group">
                        <input id="inputTerms" type="checkbox" th:field="*{terms}" onchange="activateButton(this)"/>   <label
                            class="control-label" for="terms"> I agree with the <a
                            href="#">terms and conditions</a> for Registration.
                        </label>
                    </div>

                    <!--<div class="form-group">
                         <script src='https://www.google.com/recaptcha/api.js'></script>
                         <div class="g-recaptcha"
                              data-sitekey="6LeMkmYUAAAAAHHw1k_09-rvEfEUjLgSrY6YRcLE">
                         </div>

                    </div>-->
                    <div class="form-group">
                        <button type="submit" class="btn btn-success" id="submitUserFormBtn">Register</button>
                        <span>Already registered? <a th:href="@{/login/}">Login
                                here</a></span>
                    </div>

                </form>
            </div>
        </div>
    </div>

    <script type="text/javascript"  src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"
            integrity="sha512-3P8rXCuGJdNZOnUx/03c1jOTnMn3rP63nBip5gOP2qmUh5YAdVAvFZ1E+QLZZbC1rtMrQb+mah3AfYW11RUrWA=="
            crossorigin="anonymous">
    </script>
   <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</body>
</html>

Controller

package com.emc.metalnx.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;

import org.irods.jargon.core.exception.DuplicateDataException;
import org.irods.jargon.core.exception.JargonException;
import org.irods.jargon.core.pub.domain.UserGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.emc.metalnx.controller.utils.LoggedUserUtils;
import com.emc.metalnx.core.domain.entity.DataGridUser;
import com.emc.metalnx.core.domain.exceptions.DataGridConnectionRefusedException;
import com.emc.metalnx.core.domain.exceptions.DataGridException;
import com.emc.metalnx.modelattribute.enums.ExceptionEnum;
import com.emc.metalnx.modelattribute.user.UserForm;
import com.emc.metalnx.services.interfaces.GroupService;
import com.emc.metalnx.services.interfaces.HeaderService;
import com.emc.metalnx.services.interfaces.IRODSServices;
import com.emc.metalnx.services.interfaces.UserBookmarkService;
import com.emc.metalnx.services.interfaces.UserService;
import com.emc.metalnx.services.interfaces.ZoneService;

@Controller
@RequestMapping(value = "/signup")
public class RegistrationController {

    @Autowired
    UserService userService;

    @Autowired
    GroupService groupService;

    @Autowired
    IRODSServices irodsServices;

    @Autowired
    ZoneService zoneService;

    @Autowired
    UserBookmarkService userBookmarkService;

    @Autowired
    UserBookmarkController userBookmarkController;

    @Autowired
    LoggedUserUtils loggedUserUtils;

    @Autowired
    HeaderService headerService;

    private static final Logger logger = LoggerFactory.getLogger(RegistrationController.class);
    private static final String signup_view = "signup/signup";

    @ModelAttribute("user")
    public UserForm userForm() {
        return new UserForm();
    }

    @GetMapping(value = "signup")
    public String showRegistrationForm(Model model) throws DataGridException {

        model.addAttribute("user", new UserForm());
        model.addAttribute("requestMapping", "/signup/add/action/");
        return signup_view;
    }

    /**
     * Controller method that executes action 'create user'
     *
     * @param user
     * @return the name of the template to render
     * @throws DataGridConnectionRefusedException
     */
    @RequestMapping(value = "add/action/", method = RequestMethod.POST)
    public String addUser(@ModelAttribute UserForm user, HttpServletRequest request,
            RedirectAttributes redirectAttributes) throws DataGridException {

        logger.info("addUser()");
        if (user == null) {
            throw new IllegalArgumentException("null user");
        }

        DataGridUser newUser = new DataGridUser();
        newUser.setAdditionalInfo("****");
        newUser.setUsername(user.getUsername());
        newUser.setFirstName(user.getFirstName());
        newUser.setLastName(user.getLastName());
        newUser.setEmail(user.getEmail());
        newUser.setUserType("****");
        newUser.setOrganizationalRole(user.getOrganizationalRole() != null ? user.getOrganizationalRole() : "");
        newUser.setCompany(user.getCompany() != null ? user.getCompany() : "");
        newUser.setDepartment(user.getDepartment() != null ? user.getDepartment() : "");
        logger.info("adding user:{}", newUser);

        try {
            logger.info("creating the user...");
            boolean creationSucessful = userService.createUser(newUser, user.getPassword());

            if (!creationSucessful) {
                logger.warn("unable to create the user");
                throw new DataGridException("User creation failed");
            }

            redirectAttributes.addFlashAttribute("userAddedSuccessfully", user.getUsername());

        } catch (DuplicateDataException e) {
            redirectAttributes.addFlashAttribute("duplicateUser",
                    ExceptionEnum.USERS_DATA_DUPLICATE_EXCEPTION.getCode());
            logger.error("Could not create user: ", e);
        } catch (JargonException e) {
            redirectAttributes.addFlashAttribute("error", ExceptionEnum.JARGON_EXCEPTION.getCode());
            logger.error("Could not create user: ", e);
        }

        return "redirect:/";
    }
}
trel commented 3 years ago

After a phone call, I think this issue can be closed.

There will be some investigation into a standalone registration application for iRODS itself, rather than adding a walk-up registration page to Metalnx only.

NhlamuloChauke commented 3 years ago

Thanks for the details, I am starting to understand irods much better. I am busy implementing a standalone service