3.5.1 • Published 2 years ago

@apparts/login v3.5.1

Weekly downloads
-
License
UNLICENSED
Repository
-
Last release
2 years ago

#+TITLE: Login and Signup #+DATE: 2019-02-06 Wed #+AUTHOR: Philipp Uhl

This package provides the frontend logic in form of react components for login, signup and password reset on the web. Styling has to be applied, later.

This package is designed to interact with the API as defined by [https://github.com/phuhl/apparts-login-server].

  • Usage

#+BEGIN_SRC sh npm i --save react-redux react react-dom @apparts/login @apparts/redux @apparts/api #+END_SRC

Optionally, if you want an easy start:

#+BEGIN_SRC sh npm i --save @apparts/web-components #+END_SRC

** Redux Store

This package makes use of the [https://github.com/phuhl/apparts-redux] format for redux store interoperability.

To add the store: #+BEGIN_SRC js import configureStore from "@apparts/redux";

import { loginStore } from "@apparts/login";

const { store, persistor } = configureStore({ ...loginStore }); #+END_SRC

Certain redux actions and helpers are predefined. They can be imported like this:

#+BEGIN_SRC js import { actions, getUserDataFromApiToken } from "@apparts/login"; // Use like this: // actions.logout(); #+END_SRC

You can use these actions:

  • ~renewApiToken(api)~ :: Renews the api token of the user
  • ~updateUser(user)~ :: Updates the user object by merging the provided user into the current user
  • ~login(user)~ :: Stores the user
  • ~logout()~ :: Removes the user

Helper functions:

  • ~getUserDataFromApiToken(user)~ :: Returns the content of the Api token.

** Components

Each of the components can be retrieved through a hook. Below, the signature for the ~useLogin~ hook is shown, the other hooks are analogous.

~useLogin: (config: object) => Login~ parameters:

  • ~config: ~ :: An object that takes these keys:
    • ~components: ~ :: The components to be used. At least the components ~FormikInput~, ~Button~, ~Link~, ~ErrorMessage~ have to be provided, in the format as defined in [https://github.com/phuhl/apparts-web-components] (exception: Link is not yet defined in [https://github.com/phuhl/apparts-web-components], it's definition can be seen in the Login example. The Link component is only required for Login.).
    • ~api: <@apparts/api>~ :: An API as created with [https://github.com/phuhl/apparts-frontend-api]
    • ~strings: <?object>~ :: The used texts for internationalization. You can pass your own or not pass anything, then the default strings will be used. To know, what to pass in, check out the file ~src/lang/index.js~. To overwrite only certain strings, you can import the strings with ~import { strings } from "@apparts/login";~.

The hooks return the react component. All react components are connected to the redux store, by default. They expect the ~user~ redux store, that is automatically created, as described in the previous section. Additionally, the components understand the ~lang~ store, which is a string that defines the language to be used. The definition of the ~lang~ store is optional and not automatically done.

Create screens with your favorite routing library (or however you prefer to do it) for each of these components:

*** Login

The Login component can be retrieved through the ~useLogin~ hook.

Parameters:

  • ~lang: <?string>~ :: Can be passed in through redux, defines the language. The value must be one of the keys from the ~strings~ object, that has been passed to the ~useLogin~ hook.
  • ~containerStyle: <?object>~ :: The style for the outermost div.
  • ~apiVersion: <?number>~ :: Default: 1. An optional Api version, to be passed on to @apparts/api on api calls.
  • ~onLogin: <?(user: ) => >~ :: A function that will be called, after the login has happened. The function get's passed an object, that contains ~id~, ~loginToken~, ~apiToken~, ~email~.
  • ~onLogout: <?func>~ :: A function that will be called, when the user logged out.
  • ~login: <?func>~ :: Passed through redux.
  • ~logout: <?func>~ :: Passed through redux.
  • ~logMeOut: <?bool>~ :: Default: false. If set to true, the currently logged in user will be logged out.
  • ~user: <?object>~ :: Passed through redux.
  • ~pwForgottenUrl: <?string>~ :: Default: "/passwordreset". The url, that the Link will point to, that directs the user to the password reset form.
  • ~defaulLang: <?string>~ :: Default: "en". If no value has been passed for ~lang~, the value from ~defaultLang~ will be used.

Example with [https://reactrouter.com/] as routing library:

#+BEGIN_SRC js import React from "react"; import { useLogin } from "@apparts/login"; import * as components from "@apparts/web-components"; import { useLocation, useHistory } from "react-router-dom";

// Import your configured @apparts/api here: import * as api from "helpers/api";

const LoginScreen = () => { const { search } = useLocation(), logout = new URLSearchParams(search).get("logout"), history = useHistory();

const onLogin = () => history.push("/");

const Login = useLogin({
  api,
  components: {
    ...components,
    Link: ({ to, children }) => <a href={to}>{children}</a>,
  },
});
return (
  <div style={{
         maxWidth: 600,
         margin: "auto",
         padding: 20,
         marginTop: 100,
       }}>
    <Login pwForgottenUrl="/requestpwreset"
           onLogin={() => onLogin}
           onLogout={() => history.push("/login")}
    />
  </div>
);

};

export default LoginScreen; #+END_SRC

*** Signup

The Signup component can be retrieved through the ~useSignup~ hook.

You can specify which fields should be asked for on signup. The email field will always be asked for.

Parameters:

  • ~lang: <?string>~ :: Can be passed in through redux, defines the language. The value must be one of the keys from the ~strings~ object, that has been passed to the ~useSignup~ hook.
  • ~containerStyle: <?object>~ :: The style for the outermost div.
  • ~apiVersion: <?number>~ :: Default: 1. An optional Api version, to be passed on to @apparts/api on api calls.
  • ~onSignup: <?(input: ) => >~ :: A function that will be called, after the signup has happened. The function get's passed an object, that contains all inputs from the Signup form (that means, at least ~email~).
  • ~signup: <?func>~ :: Passed through redux.
  • ~user: <?object>~ :: Passed through redux.
  • ~defaulLang: <?string>~ :: Default: "en". If no value has been passed for ~lang~, the value from ~defaultLang~ will be used.
  • ~initialValues: <?object>~ :: For additional signup fields, you have to specify their default values in this object. Key is the field name, value is the default value.
  • ~validation: <?object>~ :: For additional signup fields, you have to specify their validation functions. Use [https://github.com/jquense/yup] for validation. Key is the fields name, value is a yup-function.
  • ~firstFields: <?array>~ :: For additional signup fields before the email field, you have to pass their components into this parameter. The components must be understood by [https://formik.org].
  • ~lastFields: <?array>~ :: For additional signup fields before the email field, you have to pass their components into this parameter. The components must be understood by [https://formik.org].
  • ~transformBeforeSend: <?func>~ :: If you need to transform the input values before they are send to the API, you can pass a function. It receives an object with input name as key and value as value. The same format has to be returned.

Example:

#+BEGIN_SRC js import React from "react"; import { useSignup } from "@apparts/login"; import * as components from "@apparts/web-components";

// Import your configured @apparts/api here: import * as api from "helpers/api";

const SignupScreen = () => { const Signup = useSignup({ api, components }); return (

  <div
    style={{
      maxWidth: 600,
      margin: "auto",
      padding: 20,
      marginTop: 100,
    }}
  >
    <Signup
    onSignup={() => {/* navigate somewhere */}}/>
  </div>
);

};

export default SignupScreen; #+END_SRC

*** ResetPassword

The ResetPassword component can be retrieved through the ~useResetPassword~ hook.

It should be used on two separate screens:

  • A reset password screen, that is meant for resetting a password, after the user received an email with an url for that purpose.
  • A welcome screen, that should be linked to in the validation email, that the user should receive after signup. Here, the user can specify their password for the first time.

After the user successfully sets a password, a text will shown, that confirms the successful action. Optionally an "Ok" button can be shown (which could be configured to redirect the user to an appropriate site).

Parameters:

  • ~lang: <?string>~ :: Can be passed in through redux, defines the language. The value must be one of the keys from the ~strings~ object, that has been passed to the ~useResetPassword~ hook.
  • ~containerStyle: <?object>~ :: The style for the outermost div.
  • ~apiVersion: <?number>~ :: Default: 1. An optional Api version, to be passed on to @apparts/api on api calls.
  • ~onResetPassword: <?(input: ) => >~ :: A function that will be called, after the resetPassword has happened.
  • ~defaulLang: <?string>~ :: Default: "en". If no value has been passed for ~lang~, the value from ~defaultLang~ will be used.
  • ~validatePassword: <?object>~ :: For password policies. Use [https://github.com/jquense/yup] for validation. Key is the fields name, value is a yup-function.
  • ~welcome: <?bool>~ :: Default: false. If true, instead of resetting a password, this component sets the password for the first time, after the user received a confirmation email. The strings used differ and can be specified separately.
  • ~email: <?string>~ :: The users email. It should be taken from the query parameters of the reset password URL. Even though optional, when the value is missing, the component will not send an API request, but show an error message, that the URL used is broken.
  • ~token: <?string>~ :: The on time token that authorizes the user to set the password. It should be taken from the query parameters of the reset password URL. Even though optional, when the value is missing, the component will not send an API request, but show an error message, that the URL used is broken.
  • ~onDone: <?func>~ :: If a function is passed, after successfully resetting the password, additionally to an explanatory text there will be an "Ok" button shown. On click of that button, the ~onDone~ function is called.

Example with [https://reactrouter.com/] as routing library:

#+BEGIN_SRC js import React from "react"; import { useResetPassword } from "@apparts/login"; import * as components from "@apparts/web-components"; import { useLocation } from "react-router-dom";

// Import your configured @apparts/api here: import * as api from "helpers/api";

const ResetPasswordScreen = () => { const ResetPassword = useResetPassword({ api, components: components, }); const { search } = useLocation(), email = new URLSearchParams(search).get("email"), token = new URLSearchParams(search).get("token"); return (

  <div
    style={{
      maxWidth: 600,
      margin: "auto",
      padding: 20,
      marginTop: 100,
    }}
  >
    <ResetPassword email={email} token={token} />
  </div>
);

};

export default ResetPasswordScreen; #+END_SRC

*** RequestPasswordReset

The RequestPasswordReset component can be retrieved through the ~useRequestPasswordReset~ hook.

After the user successfully requests a password reset, a text will shown, that confirms the successful action.

Parameters:

  • ~lang: <?string>~ :: Can be passed in through redux, defines the language. The value must be one of the keys from the ~strings~ object, that has been passed to the ~useRequestPasswordReset~ hook.
  • ~containerStyle: <?object>~ :: The style for the outermost div.
  • ~apiVersion: <?number>~ :: Default: 1. An optional Api version, to be passed on to @apparts/api on api calls.
  • ~onRequestPasswordReset: <?(input: ) => >~ :: A function that will be called, after the password reset request has happened.
  • ~defaulLang: <?string>~ :: Default: "en". If no value has been passed for ~lang~, the value from ~defaultLang~ will be used.

Example with [https://reactrouter.com/] as routing library:

#+BEGIN_SRC js import React from "react"; import { useRequestPasswordReset } from "@apparts/login"; import * as components from "@apparts/web-components";

// Import your configured @apparts/api here:
import * as api from "helpers/api";

const RequestPWResetScreen = () => { const RequestPWReset = useRequestPasswordReset({ api, components: components, }); return (

    <div
      style={{
        maxWidth: 600,
        margin: "auto",
        padding: 20,
        marginTop: 100,
      }}
    >
      <RequestPWReset />
    </div>
);

};

export default RequestPWResetScreen; #+END_SRC

** Redirect to Login and back

In many applications you will want an unauthenticated user to be presented with a login form and after login redirected to the URL, that the user actually wanted to visit. @apparts/login provides some tools for this purpose.

  • ~utils.buildRedirector : (queryParams, ?redirectExcludes) => {str, obj}~ ::
    • =queryParams= is the search string, that should be present after all redirects.
    • ~redirectExcludes~ is an optional array of paths, on which you don't want a redirect to happen (e.g. on your login or signup page).
    • The function returns an object with ~str~, the search string, that the login page will use to redirect after login and ~obj~, an object with the search parameters as of ~str~ as key-value pairs.
  • ~utils.buildGetLoggedInUser : (goToLogin) => user~ :: A function, used to build a ~useUser~ function. It returns the currently logged in user (if any) and if no user is logged in, it calls the ~goToLogin~ parameter function. That function then can redirect to the login page.
  • ~utils.getRedirectUrl : (redirect, rsearch) => string~ :: A function, that takes the search parameters ~redirect~ and ~rsearch~ as strings (as they can be present on the login page) and builds the url to push to, after successful login.

Within a utility file (here called ~utils~), import the utils and export functions to your liking. Here an example using [https://reactrouter.com/] as routing library:

#+BEGIN_SRC js // utils.js import { useHistory } from "react-router-dom";

import { utils } from "@apparts/login";

export const useRedirector = () => { const { search } = window.location; return utils.buildRedirector(search, "login"); };

export const useUser = () => { const history = useHistory(); utils.buildGetLoggedInUser(() => { const redirectQuery = useRedirector(); history.push("/login" + redirectQuery.str); }); };

export const getRedirectUrl = utils.getRedirectUrl; #+END_SRC

On a page, that should redirect to login, if no authenticated user was found, use the ~useUser~ function to retrieve the user. It will automatically redirect to =/login= if no user is logged in.

On the login screen, use something like this to do the redirect:

Example with [https://reactrouter.com/] as routing library:

#+BEGIN_SRC js // ...

// import from the utility file, you created earlier: import { getRedirectUrl } from "utils";

const LoginScreen = () => { const { search } = useLocation(), redirect = new URLSearchParams(search).get("redirect"), rsearch = new URLSearchParams(search).get("rsearch"), // ... history = useHistory();

const onLogin = () => {
  if (redirect) {
    history.push(getRedirectUrl(redirect, rsearch));
  } else {
    history.push("/");
  }
};

const Login = useLogin({
// ...
});
return (/* ... */);

};

export default LoginScreen; #+END_SRC

3.5.1

2 years ago

3.5.0

2 years ago

3.4.2

2 years ago

3.4.1

2 years ago

3.3.1

3 years ago

3.3.0

3 years ago

3.2.0

3 years ago

3.1.3

3 years ago

3.1.2

3 years ago

3.1.1

3 years ago

3.1.0

3 years ago

3.0.1

3 years ago

3.1.4

3 years ago

3.0.0

3 years ago