// Links sent by email (lib/emails.ts): "verify" confirms an address, "reset" sets a new password.
//
// Only a SHA-256 hash of the token in the link is stored. `email` is the address it went to, so a
// link stops working once the account's email changes. Only the server (a superuser) reads them.
migrate(
(app) => {
const users = app.findCollectionByNameOrId("users");
const collection = new Collection({
type: "base",
name: "email_tokens",
listRule: null,
viewRule: null,
createRule: null,
updateRule: null,
deleteRule: null,
fields: [
{ type: "relation", name: "user", collectionId: users.id, maxSelect: 1, required: true, cascadeDelete: true },
{ type: "select", name: "purpose", values: ["verify", "reset"], maxSelect: 1, required: true },
{ type: "text", name: "email", max: 200, required: true },
{ type: "text", name: "token_hash", max: 64, required: true },
{ type: "number", name: "expires_at", onlyInt: true, min: 0, required: true },
{ type: "number", name: "created_at", onlyInt: true, min: 0, required: true },
],
indexes: [
"CREATE UNIQUE INDEX idx_email_tokens_hash ON email_tokens (token_hash)",
"CREATE INDEX idx_email_tokens_user ON email_tokens (user, purpose)",
],
});
app.save(collection);
},
(app) => {
app.delete(app.findCollectionByNameOrId("email_tokens"));
},
);