<commit_before># User Invitations

## Summary

Add "invite a friend" functionality to your application. Invite friends using [SendGrid](https://SendGrid.com/) and keep track of your invites with Firestore.

## Details

This Mod defines two callable functions - one to send invitations via email, and the other that will be triggered upon acceptance of an email invitation. **Users must be authenticated for the functions to be triggered.**

This Mod also requires a SendGrid account. They can be created for free at https://SendGrid.com/.

#####Inviting a user
The invite flow begins when an authenticated user enters the email address of the friend they wish to invite. This email is written to an invitations array[1] in Firestore, which triggers the Mod function that sends invitations.

[1] How invitations sent by user are stored in Firestore
```
users:
  12345:
    name: Roman
    invitations:
    - email: <EMAIL>
```

The invitation email that is sent is defined in the Mod, in `index.js` line 54. The invitation is written in HTML. Feel free to edit this invitation to control what your invitees will see. The default is as follows:
```
<p>Hi there ${email},</p>
<p>I'm using ${APP_NAME} and I'd love for you to join me! <a href="${acceptUrl}">Accept invitation</a></p>
<p>- ${auth.token.name} (via ${APP_NAME})</p>
```

#####Receiving an invitation
The Mod generates an invitation token and uses SendGrid to send an invitation to the given email address, along with a URL token of the form `?invitation=theVeryLongTokenHere`. It stores this generated token in an internal Firestore path[2].

[2] How accept tokens are stored in Firestore
```
invitation_mods_internal:
  tokens:
    theVeryLongTokenHere:
      sender_uid: 12345
      receiver_email: <EMAIL>
```

When the invitee receives the invitation, they click the link in the invite where they should be redirected to your app. You must authenticate this user. The app is then responsible for grabbing the invitation query string and storing a “accepted tokens” entry in Firestore[3].

[3] How accepted tokens are stored in Firestore
```users:
  87345:
    name: John
    accept_invite_tokens:
    - <PASSWORD>TokenHere
```

#####Accepting an invitation
The Mod has a function that watches for writes of accepted tokens to Firestore. This functions is triggered, which finalizes the invitation. The function also deletes the `accept_invite_tokens` record for the receivre and the `invitations` record for the sender[4].

[4] How data should look after invite has been accepted
```
users:
  12345:
    name: Roman
    friend_ids:<commit_msg>fix readme<commit_after># User Invitations

## Summary

Add "invite a friend" functionality to your application. Invite friends using [SendGrid](https://SendGrid.com/) and keep track of your invites with Firestore.

## Details

This Mod defines two callable functions - one to send invitations via email, and the other that will be triggered upon acceptance of an email invitation. **Users must be authenticated for the functions to be triggered.**

This Mod also requires a SendGrid account. They can be created for free at https://SendGrid.com/.

##### Inviting a user
The invite flow begins when an authenticated user enters the email address of the friend they wish to invite. This email is written to an invitations array[1] in Firestore, which triggers the Mod function that sends invitations.

[1] How invitations sent by user are stored in Firestore
```
users:
  12345:
    name: Roman
    invitations:
    - email: <EMAIL>
```

The invitation email that is sent is defined in the Mod, in `index.js` line 54. The invitation is written in HTML. Feel free to edit this invitation to control what your invitees will see. The default is as follows:
```
<p>Hi there ${email},</p>
<p>I'm using ${APP_NAME} and I'd love for you to join me! <a href="${acceptUrl}">Accept invitation</a></p>
<p>- ${auth.token.name} (via ${APP_NAME})</p>
```

##### Receiving an invitation
The Mod generates an invitation token and uses SendGrid to send an invitation to the given email address, along with a URL token of the form `?invitation=theVeryLongTokenHere`. It stores this generated token in an internal Firestore path[2].

[2] How accept tokens are stored in Firestore
```
invitation_mods_internal:
  tokens:
    theVeryLongTokenHere:
      sender_uid: 12345
      receiver_email: <EMAIL>
```

When the invitee receives the invitation, they click the link in the invite where they should be redirected to your app. You must authenticate this user. The app is then responsible for grabbing the invitation query string and storing a “accepted tokens” entry in Firestore[3].

[3] How accepted tokens are stored in Firestore
```users:
  87345:
    name: John
    accept_invite_tokens:
    - theVeryLongTokenHere
```

##### Accepting an invitation
The Mod has a function that watches for writes of accepted tokens to Firestore. This functions is triggered, which finalizes the invitation. The function also deletes the `accept_invite_tokens` record for the receivre and the `invitations` record for the sender[4].

[4] How data should look after invite has been accepted
```
users:
  12345:
    name: Roman
    friend_ids:
{'fraction_non_alphanumeric': 0.07593480345158198, 'fraction_numerical': 0.011505273250239693, 'mean_word_length': 4.37178166838311, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 24, 'https://': 4, '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': '5134369', 'n_tokens_mistral': 1444, 'n_tokens_neox': 1365, 'n_words': 726}