adds unique has column because of mysql unique character limitation

Signed-off-by: Billy Stalnaker <bstalnaker@roadie.com>
This commit is contained in:
Billy Stalnaker
2025-03-25 13:14:22 -04:00
parent 4d772f6d74
commit 08972ee879
5 changed files with 63 additions and 15 deletions
@@ -13,29 +13,42 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const crypto = require('crypto');
exports.up = async function up(knex) {
await knex.schema.alterTable('user_settings', table => {
table.string('topic').nullable().after('origin');
});
await knex.schema.table('user_settings', table => {
table.string('settings_key_hash', 64).notNullable();
table.dropUnique([], 'user_settings_unique_idx');
});
await knex.schema.alterTable('user_settings', table => {
table.unique(['user(255)', 'channel(255)', 'origin(255)', 'topic(255)'], {
indexName: 'user_settings_unique_idx',
});
table.unique(['settings_key_hash'], 'user_settings_unique_idx');
});
const rows = await knex('user_settings').select('user', 'channel', 'origin');
for (const row of rows) {
const rawKey = `${row.user}|${row.channel}|${row.origin}|}`;
const hash = crypto.createHash('sha256').update(rawKey).digest('hex');
await knex('user_settings')
.where({
user: row.user,
channel: row.channel,
origin: row.origin,
topic: row.topic,
})
.update({ settings_key_hash: hash });
}
};
exports.down = async function down(knex) {
await knex.schema.table('user_settings', table => {
table.dropUnique([], 'user_settings_unique_idx');
table.dropColumn('settings_key_hash');
table.dropColumn('topic');
});
await knex.schema.alterTable('user_settings', table => {
table.dropColumn('topic');
table.unique(['user', 'channel', 'origin'], {
indexName: 'user_settings_unique_idx',
});
+9 -8
View File
@@ -63,15 +63,16 @@
## Table `user_settings`
| Column | Type | Nullable | Max Length | Default |
| --------- | ------------------- | -------- | ---------- | ------- |
| `channel` | `character varying` | false | 255 | - |
| `enabled` | `boolean` | false | - | `true` |
| `origin` | `character varying` | false | 255 | - |
| `topic` | `character varying` | true | 255 | - |
| `user` | `character varying` | false | 255 | - |
| Column | Type | Nullable | Max Length | Default |
| ------------------- | ------------------- | -------- | ---------- | ------- |
| `channel` | `character varying` | false | 255 | - |
| `enabled` | `boolean` | false | - | `true` |
| `origin` | `character varying` | false | 255 | - |
| `settings_key_hash` | `character varying` | false | 64 | - |
| `topic` | `character varying` | true | 255 | - |
| `user` | `character varying` | false | 255 | - |
### Indices
- `user_settings_unique_idx` (`user`, `channel`, `origin`, `topic`) unique
- `user_settings_unique_idx` (`settings_key_hash`) unique
- `user_settings_user_idx` (`user`)
@@ -24,6 +24,7 @@ import {
TopicGetOptions,
} from './NotificationsStore';
import {
generateSettingsHash,
Notification,
NotificationSettings,
notificationSeverities,
@@ -584,6 +585,7 @@ export class DatabaseNotificationsStore implements NotificationsStore {
settings: NotificationSettings;
}): Promise<void> {
const rows: {
settings_key_hash: string;
user: string;
channel: string;
origin: string;
@@ -594,6 +596,12 @@ export class DatabaseNotificationsStore implements NotificationsStore {
options.settings.channels.forEach(channel => {
channel.origins.forEach(origin => {
rows.push({
settings_key_hash: generateSettingsHash(
options.user,
channel.id,
origin.id,
null,
),
user: options.user,
channel: channel.id,
origin: origin.id,
@@ -603,6 +611,12 @@ export class DatabaseNotificationsStore implements NotificationsStore {
origin.topics?.forEach(topic => {
rows.push({
settings_key_hash: generateSettingsHash(
options.user,
channel.id,
origin.id,
topic.id,
),
user: options.user,
channel: channel.id,
origin: origin.id,
@@ -11,6 +11,14 @@ export type ChannelSetting = {
origins: OriginSetting[];
};
// @public (undocumented)
export const generateSettingsHash: (
user: string,
channel: string,
origin: string,
topic: string | null,
) => string;
// @public (undocumented)
export const getProcessorFiltersFromConfig: (
config: Config,
+12
View File
@@ -14,6 +14,7 @@
* limitations under the License.
*/
import { NotificationSettings } from './types';
import crypto from 'crypto';
/** @public */
export const isNotificationsEnabledFor = (
@@ -40,3 +41,14 @@ export const isNotificationsEnabledFor = (
}
return topic.enabled;
};
/** @public */
export const generateSettingsHash = (
user: string,
channel: string,
origin: string,
topic: string | null,
): string => {
const rawKey = `${user}|${channel}|${origin}|${topic ?? ''}`;
return crypto.createHash('sha256').update(rawKey).digest('hex');
};