text: /**
   * User.js
   *
   * A user who can log in to this application.
   */
  
  module.exports = {
  
    attributes: {
  
      //  ╔═╗╦═╗╦╔╦╗╦╔╦╗╦╦  ╦╔═╗╔═╗
      //  ╠═╝╠╦╝║║║║║ ║ ║╚╗╔╝║╣ ╚═╗
      //  ╩  ╩╚═╩╩ ╩╩ ╩ ╩ ╚╝ ╚═╝╚═╝
  
      emailAddress: {
        type: 'string',
        required: true,
        unique: true,
        isEmail: true,
        maxLength: 200,
        example: 'carol.reyna@microsoft.com'
      },
  
      password: {
        type: 'string',
        required: true,
        description: 'Securely hashed representation of the user\'s login password.',
        protect: true,
        example: '2$28a8eabna301089103-13948134nad'
      },
  
      fullName: {
        type: 'string',
        required: true,
        description: 'Full representation of the user\'s name',
        maxLength: 120,
        example: 'Lisa Microwave van der Jenny'
      },
  
      isSuperAdmin: {
        type: 'boolean',
        description: 'Whether this user is a "super admin" with extra permissions, etc.',
        extendedDescription:
  `Super admins might have extra permissions, see a different default home page when they log in,
  or even have a completely different feature set from normal users.  In this app, the \`isSuperAdmin\`
  flag is just here as a simple way to represent two different kinds of users.  Usually, it's a good idea
  to keep the data model as simple as possible, only adding attributes when you actually need them for
  features being built right now.
  
  For example, a "super admin" user for a small to medium-sized e-commerce website might be able to
  change prices, deactivate seasonal categories, add new offerings, and view live orders as they come in.
  On the other hand, for an e-commerce website like Walmart.com that has undergone years of development
  by a large team, those administrative features might be split across a few different roles.
  
  So, while this \`isSuperAdmin\` demarcation might not be the right approach forever, it's a good place to start.`
      },
  
      passwordResetToken: {
        type: 'string',
        description: 'A unique token used to verify the user\'s identity when recovering a password.  Expires after 1 use, or after a set amount of time has elapsed.'
      },
  
      passwordResetTokenExpiresAt: {
        type: 'number',
        description: 'A JS timestamp (epoch ms) representing the moment when this user\'s `passwordResetToken` will expire (or 0 if the user currently has no such token).',
        example: 1502844074211
      },
  
      stripeCustomerId: {
        type: 'string',
        protect: true,
        description: 'The id of the customer entry in Stripe associated with this user (or empty string if this user is not linked to a Stripe customer -- e.g. if billing features are not enabled).',
        extendedDescription:
  `Just because this value is set doesn't necessarily mean that this user has a billing card.
  It just means they have a customer entry in Stripe, which might or might not have a billing card.`
      },
  
      hasBillingCard: {
        type: 'boolean',
        description: 'Whether this user has a default billing card hooked up as their payment method.',
        extendedDescription:
  `More specifically, this indcates whether this user record's linked customer entry in Stripe has
  a default payment source (i.e. credit card).  Note that a user have a \`stripeCustomerId\`
  without necessarily having a billing card.`
      },
  
      billingCardBrand: {
        type: 'string',
        example: 'Visa',
        description: 'The brand of this user\'s default billing card (or empty string if no billing card is set up).',
        extendedDescription: 'To ensure PCI compliance, this data comes from Stripe, where it reflects the user\'s default payment source.'
      },
  
      billingCardLast4: {
        type: 'string',
        example: '4242',
        description: 'The last four digits of the card number for this user\'s default billing card (or empty string if no billing card is set up).',
        extendedDescription: 'To ensure PCI compliance, this data comes from Stripe, where it reflects the user\'s default payment source.'
      },
  
      billingCardExpMonth: {
        type: 'string',
        example: '08',
        description: 'The two-digit expiration month from this user\'s default billing card, formatted as MM (or empty string if no billing card is set up).',
        extendedDescription: 'To ensure PCI compliance, this data comes from Stripe, where it reflects the user\'s default payment source.'
      },
  
      billingCardExpYear: {
        type: 'string',
        example: '2023',
        description: 'The four-digit expiration year from this user\'s default billing card, formatted as YYYY (or empty string if no credit card is set up).',
        extendedDescription: 'To ensure PCI compliance, this data comes from Stripe, where it reflects the user\'s default payment source.'
      },
  
      emailProofToken: {
        type: 'string',
        description: 'A pseudorandom, probabilistically-unique token for use in our account verification emails.'
      },
  
      emailProofTokenExpiresAt: {
        type: 'number',
        description: 'A JS timestamp (epoch ms) representing the moment when this user\'s `emailProofToken` will expire (or 0 if the user currently has no such token).',
        example: 1502844074211
      },
  
      emailStatus: {
        type: 'string',
        isIn: ['unconfirmed', 'changeRequested', 'confirmed'],
        defaultsTo: 'confirmed',
        description: 'The confirmation status of the user\'s email address.',
        extendedDescription:
  `Users might be created as "unconfirmed" (e.g. normal signup) or as "confirmed" (e.g. hard-coded
  admin users).  When the email verification feature is enabled, new users created via the
  signup form have \`emailStatus: 'unconfirmed'\` until they click the link in the confirmation email.
  Similarly, when an existing user changes their email address, they switch to the "changeRequested"
  email status until they click the link in the confirmation email.`
      },
  
      emailChangeCandidate: {
        type: 'string',
        description: 'The (still-unconfirmed) email address that this user wants to change to.'
      },
  
      tosAcceptedByIp: {
        type: 'string',
        description: 'The IP (ipv4) address of the request that accepted the terms of service.',
        extendedDescription: 'Useful for certain types of businesses and regulatory requirements (KYC, etc.)',
        moreInfoUrl: 'https://en.wikipedia.org/wiki/Know_your_customer'
      },
  
      lastSeenAt: {
        type: 'number',
        description: 'A JS timestamp (epoch ms) representing the moment at which this user most recently interacted with the backend while logged in (or 0 if they have not interacted with the backend at all yet).',
        example: 1502844074211
      },
  
      //  ╔═╗╔╦╗╔╗ ╔═╗╔╦╗╔═╗
      //  ║╣ ║║║╠╩╗║╣  ║║╚═╗
      //  ╚═╝╩ ╩╚═╝╚═╝═╩╝╚═╝
      // n/a
  
      //  ╔═╗╔═╗╔═╗╔═╗╔═╗╦╔═╗╔╦╗╦╔═╗╔╗╔╔═╗
      //  ╠═╣╚═╗╚═╗║ ║║  ║╠═╣ ║ ║║ ║║║║╚═╗
      //  ╩ ╩╚═╝╚═╝╚═╝╚═╝╩╩ ╩ ╩ ╩╚═╝╝╚╝╚═╝
      friends: { collection: 'User' }
  
    },
  
  
  };
  