Separation of responsibilities between infrastructure and services (business) layers

33 Views Asked by At

In application user should be able to authorize using his twitch account, here is how business requirements looks like:

  1. for twitch authorization user should be redirected (by the backend application) to the twitch authentication page
  2. after logging in on twitch side:
    _ if user was not found in our application - new user should be created and then logged in to our application
    _ if user already existed - it should be logged in
  3. then user should be redirected back to the frontend application

And here is how I've managed to do it:

// this class represents business logic
class TwitchAuthService {
  // this method returns url and then controller redirects user to the appropriate page
  public getRedirectionUrlToStartAuth = (
    { successUrl, failUrl }: { successUrl: string; failUrl: string; }
  ): string => {
    return 'https://id.twitch.tv/oauth2/authorize?' +
      new URLSearchParams({
        response_type: 'code',
        client_id: this.twitchId,
        redirect_uri: this.getRedirectUrl(),
        scope: 'user:read:email',
        state: `successUrl=${successUrl}&failUrl=${failUrl}`,
      })
  }
  
  // after receiving token from twitch, we 
  // - return already existing user or
  // - create a new one and return it
  authenticateUser() { ... }
}

And at the moment when I receive callback from twitch, I have to parse successUrl and failUrl parameters from twitch-url in response for further redirection (I've provided these parameters earlier while using getRedirectionUrlToStartAuth method)

I've created a separate method for this "parsing" functionality, getRedirectUrlsFromCallback but where should I locate it?

Is it still part of business logic? Or should I create some infrastructure service for Twitch and put this method here? Or it simply can be added as private method of the controller?

  public getRedirectUrlsFromCallback = (state: string): { successUrl: string; failUrl: string } => {
    const urlParams = new URLSearchParams(state);
    const successUrl = urlParams.get('successUrl');
    const failUrl = urlParams.get('failUrl');

    if (!successUrl || !failUrl) {
      throw new IncorrectCallbackUrlError();
    }

    return {
      successUrl,
      failUrl,
    }
  }

0

There are 0 best solutions below