• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

safe-global / safe-client-gateway / 6824988676

10 Nov 2023 12:47PM UTC coverage: 90.808% (-0.3%) from 91.077%
6824988676

push

github

web-flow
Add Emails Datasource (#829)

Datasource

Adds a `IEmailDataSource` – this component can be used to interact with the underlying data source which stores the email addresses for a given signer, for a given safe address on a specific chain. The following functionality was added:
  * `saveEmail` – saves an email address in the database. Returns a verification code if it was successfully stored.
  * `setVerificationCode` – resets the verification code for a signer. Returns the new verification code if successful.
  * `verifyEmail` – verifies a specific email given the code that was returned on registration. If the code matches then the email is considered verified. There's a configurable expiration time for the code that was introduced for security reasons – the code needs to be verified within a given timeframe to be considered valid. If the code is not verified in this timeframe then it should be reset.

Database

- Adds one table – `signer_emails` under the `emails` schema.
- A unique constraint exists for entries on `signer_emails`: an entry is considered unique when the following fields are considered: `chain_id`, `safe_address`, `signer`.

Migration Support

Migration support was added. Migration files need to be under the `migrations` folder. Inside it, a migration folder should be created with 5 digits and under that folder, an `index.sql` containing the migration file. 

For example, the initial migration has the following structure:

migrations/
└── 00001_initial
    └── index.sql

The initial migration creates the `signer_emails` table. The migration is done whenever the `PostgresDatabaseModule` is initialised (via the `PostgresDatabaseMigrationHook`).

Note on running multiple instances of the service: an advisory lock is acquired so that only one instance performs the migration. Other instances will wait for the lock to be released (via `pg_advisory_lock`). Migrations should be idempotent so that the final state of th... (continued)

1368 of 1646 branches covered (0.0%)

Branch coverage included in aggregate %.

19 of 40 new or added lines in 6 files covered. (47.5%)

5103 of 5480 relevant lines covered (93.12%)

163.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/datasources/db/postgres-database.migration.hook.ts
NEW
1
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
×
NEW
2
import { ILoggingService, LoggingService } from '@/logging/logging.interface';
×
NEW
3
import * as shift from 'postgres-shift';
×
NEW
4
import postgres from 'postgres';
×
5

6
/**
7
 * The {@link PostgresDatabaseMigrationHook} is a Module Init hook meaning
8
 * that it will be executed once the dependencies are resolved.
9
 *
10
 * This happens before the Application Bootstraps, so route listeners are not
11
 * initiated and potentially generating queries.
12
 */
13
@Injectable({})
NEW
14
export class PostgresDatabaseMigrationHook implements OnModuleInit {
×
NEW
15
  private static LOCK_MAGIC_NUMBER = 132;
×
16

17
  constructor(
NEW
18
    @Inject('DB_INSTANCE') private readonly sql: postgres.Sql,
×
NEW
19
    @Inject(LoggingService) private readonly loggingService: ILoggingService,
×
20
  ) {}
21

22
  async onModuleInit() {
NEW
23
    this.loggingService.info('Checking migrations');
×
NEW
24
    try {
×
25
      // Acquire lock to perform a migration.
26
      // If the lock is not acquired, then a migration is being executed by another instance.
27
      // Migrations should strive to be idempotent as they can be executed by multiple instances
28
      // on the same database.
NEW
29
      await this
×
30
        .sql`SELECT pg_advisory_lock(${PostgresDatabaseMigrationHook.LOCK_MAGIC_NUMBER})`;
31
      // Perform migration
NEW
32
      await shift({ sql: this.sql });
×
NEW
33
      this.loggingService.info('Pending migrations executed');
×
34
    } catch (e) {
35
      // If there's an error performing a migration, we should throw the error
36
      // and prevent the service from starting
NEW
37
      this.loggingService.error(e);
×
NEW
38
      throw e;
×
39
    } finally {
40
      // the lock should be released if the migration completed (successfully or not)
NEW
41
      await this
×
42
        .sql`SELECT pg_advisory_unlock(${PostgresDatabaseMigrationHook.LOCK_MAGIC_NUMBER})`;
43
    }
44
  }
45
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc