<commit_before>import{ Observable } from 'rx';
import { observeMethod, observeQuery } from '../utils/rx';
import { getSocialProvider } from '../utils/auth';
import debugFactory from 'debug';

const debug = debugFactory('fcc:userIdent');

export default function({ models }) {
  const { User, UserIdentity, UserCredential } = models;
  const findUserById = observeMethod(User, 'findById');
  const findIdent = observeMethod(UserIdentity, 'findOne');

  UserIdentity.link = function(
    userId,
    provider,
    authScheme,
    profile,
    credentials,
    options = {},
    cb
  ) {
    if (typeof options === 'function' && !cb) {
      cb = options;
      options = {};
    }
    const user$ = findUserById(userId);
    const query = {
      where: {
        provider: getSocialProvider(provider),
        externalId: profile.id
      }
    };

    debug('link identity query', query);
    findIdent(query)
      .flatMap(identity => {
        const modified = new Date();
        if (!identity) {
          return observeQuery(UserIdentity, 'create', {
            provider: getSocialProvider(provider),
            externalId: profile.id,
            authScheme,
            profile,
            credentials,
            userId,
            created: modified,
            modified
          });
        }
        if (identity.userId.toString() !== userId.toString()) {
          return Observable.throw(
            new Error('An account is already linked to that profile')
          );
        }
        identity.credentials = credentials;
        return observeQuery(identity, 'updateAttributes', {
          profile,
          credentials,
          modified
        });
      })
      .withLatestFrom(user$, (identity, user) => ({ identity, user }))
      .subscribe(
        ({ identity, user }) => {
          cb(null, user, identity);
        },
        cb
      );
  };

  UserCredential.link = UserIdentity.link.bind(UserIdentity);
}<commit_msg>add descriptive message to failed account linking attempt<commit_after>import{ Observable } from 'rx';
import { observeMethod, observeQuery } from '../utils/rx';
import { getSocialProvider } from '../utils/auth';
import debugFactory from 'debug';

const debug = debugFactory('fcc:userIdent');

export default function({ models }) {
  const { User, UserIdentity, UserCredential } = models;
  const findUserById = observeMethod(User, 'findById');
  const findIdent = observeMethod(UserIdentity, 'findOne');

  UserIdentity.link = function(
    userId,
    provider,
    authScheme,
    profile,
    credentials,
    options = {},
    cb
  ) {
    if (typeof options === 'function' && !cb) {
      cb = options;
      options = {};
    }
    const user$ = findUserById(userId);
    const query = {
      where: {
        provider: getSocialProvider(provider),
        externalId: profile.id
      }
    };

    debug('link identity query', query);
    findIdent(query)
      .flatMap(identity => {
        const modified = new Date();
        if (!identity) {
          return observeQuery(UserIdentity, 'create', {
            provider: getSocialProvider(provider),
            externalId: profile.id,
            authScheme,
            profile,
            credentials,
            userId,
            created: modified,
            modified
          });
        }
        if (identity.userId.toString() !== userId.toString()) {
          return Observable.throw(
            new Error("It looks like you already have an account associated with that sign in method. Here's what you can do: 1) Sign out of this account. 2) Use that sign in method to sign into your other account. 3) Delete that account. 4) Then sign back into this account and you'll be able to link it here. If you need help, send us an email at <EMAIL>.")
          );
        }
        identity.credentials = credentials;
        return observeQuery(identity, 'updateAttributes', {
          profile,
          credentials,
          modified
        });
      })
      .withLatestFrom(user$, (identity, user) => ({ identity, user }))
      .subscribe(
        ({ identity, user }) => {
          cb(null, user, identity);
        },
        cb
      );
  };

  UserCredential.link = UserIdentity.link.bind(UserIdentity);
}
{'fraction_non_alphanumeric': 0.11571025399811853, 'fraction_numerical': 0.0009407337723424271, 'mean_word_length': 2.2122356495468276, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '342332', 'n_tokens_mistral': 1115, 'n_tokens_neox': 1108, 'n_words': 317}