Merge pull request #3026 from gradido/federation-fix-database-public-key-length

refactor(database): fix database public key lengths
This commit is contained in:
Ulf Gebhardt 2023-07-06 14:04:21 +02:00 committed by GitHub
commit 4fa5147212
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 171 additions and 23 deletions

View File

@ -12,7 +12,7 @@ Decimal.set({
})
const constants = {
DB_VERSION: '0067-private_key_in_community_table',
DB_VERSION: '0068-community_tables_public_key_length',
DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info

View File

@ -73,9 +73,7 @@ describe('validate Communities', () => {
} as Response<unknown>
})
const variables1 = {
publicKey: Buffer.from(
'1111111111111111111111111111111111111111111111111111111111111111',
),
publicKey: Buffer.from('11111111111111111111111111111111'),
apiVersion: '1_0',
endPoint: 'http//localhost:5001/api/',
lastAnnouncedAt: new Date(),
@ -108,7 +106,7 @@ describe('validate Communities', () => {
expect(logger.warn).toBeCalledWith(
'Federation: received not matching publicKey:',
'somePubKey',
expect.stringMatching('1111111111111111111111111111111111111111111111111111111111111111'),
expect.stringMatching('11111111111111111111111111111111'),
)
})
})
@ -120,15 +118,13 @@ describe('validate Communities', () => {
return {
data: {
getPublicKey: {
publicKey: '1111111111111111111111111111111111111111111111111111111111111111',
publicKey: '11111111111111111111111111111111',
},
},
} as Response<unknown>
})
const variables1 = {
publicKey: Buffer.from(
'1111111111111111111111111111111111111111111111111111111111111111',
),
publicKey: Buffer.from('11111111111111111111111111111111'),
apiVersion: '1_0',
endPoint: 'http//localhost:5001/api/',
lastAnnouncedAt: new Date(),
@ -174,15 +170,13 @@ describe('validate Communities', () => {
return {
data: {
getPublicKey: {
publicKey: '1111111111111111111111111111111111111111111111111111111111111111',
publicKey: '11111111111111111111111111111111',
},
},
} as Response<unknown>
})
const variables2 = {
publicKey: Buffer.from(
'1111111111111111111111111111111111111111111111111111111111111111',
),
publicKey: Buffer.from('11111111111111111111111111111111'),
apiVersion: '1_1',
endPoint: 'http//localhost:5001/api/',
lastAnnouncedAt: new Date(),
@ -222,9 +216,7 @@ describe('validate Communities', () => {
let dbCom: DbFederatedCommunity
beforeEach(async () => {
const variables3 = {
publicKey: Buffer.from(
'1111111111111111111111111111111111111111111111111111111111111111',
),
publicKey: Buffer.from('11111111111111111111111111111111'),
apiVersion: '2_0',
endPoint: 'http//localhost:5001/api/',
lastAnnouncedAt: new Date(),

View File

@ -0,0 +1,63 @@
import {
BaseEntity,
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm'
@Entity('communities')
export class Community extends BaseEntity {
@PrimaryGeneratedColumn('increment', { unsigned: true })
id: number
@Column({ name: 'foreign', type: 'bool', nullable: false, default: true })
foreign: boolean
@Column({ name: 'url', length: 255, nullable: false })
url: string
@Column({ name: 'public_key', type: 'binary', length: 32, nullable: false })
publicKey: Buffer
@Column({ name: 'private_key', type: 'binary', length: 64, nullable: true })
privateKey: Buffer | null
@Column({
name: 'community_uuid',
type: 'char',
length: 36,
nullable: true,
collation: 'utf8mb4_unicode_ci',
})
communityUuid: string | null
@Column({ name: 'authenticated_at', type: 'datetime', nullable: true })
authenticatedAt: Date | null
@Column({ name: 'name', type: 'varchar', length: 40, nullable: true })
name: string | null
@Column({ name: 'description', type: 'varchar', length: 255, nullable: true })
description: string | null
@CreateDateColumn({ name: 'creation_date', type: 'datetime', nullable: true })
creationDate: Date | null
@CreateDateColumn({
name: 'created_at',
type: 'datetime',
default: () => 'CURRENT_TIMESTAMP(3)',
nullable: false,
})
createdAt: Date
@UpdateDateColumn({
name: 'updated_at',
type: 'datetime',
onUpdate: 'CURRENT_TIMESTAMP(3)',
nullable: true,
})
updatedAt: Date | null
}

View File

@ -0,0 +1,51 @@
import {
BaseEntity,
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm'
@Entity('federated_communities')
export class FederatedCommunity extends BaseEntity {
@PrimaryGeneratedColumn('increment', { unsigned: true })
id: number
@Column({ name: 'foreign', type: 'bool', nullable: false, default: true })
foreign: boolean
@Column({ name: 'public_key', type: 'binary', length: 32, default: null, nullable: true })
publicKey: Buffer
@Column({ name: 'api_version', length: 10, nullable: false })
apiVersion: string
@Column({ name: 'end_point', length: 255, nullable: false })
endPoint: string
@Column({ name: 'last_announced_at', type: 'datetime', nullable: true })
lastAnnouncedAt: Date | null
@Column({ name: 'verified_at', type: 'datetime', nullable: true })
verifiedAt: Date | null
@Column({ name: 'last_error_at', type: 'datetime', nullable: true })
lastErrorAt: Date | null
@CreateDateColumn({
name: 'created_at',
type: 'datetime',
default: () => 'CURRENT_TIMESTAMP(3)',
nullable: false,
})
createdAt: Date
@UpdateDateColumn({
name: 'updated_at',
type: 'datetime',
onUpdate: 'CURRENT_TIMESTAMP(3)',
nullable: true,
})
updatedAt: Date | null
}

View File

@ -1 +1 @@
export { Community } from './0067-private_key_in_community_table/Community'
export { Community } from './0068-community_tables_public_key_length/Community'

View File

@ -1 +1 @@
export { FederatedCommunity } from './0065-refactor_communities_table/FederatedCommunity'
export { FederatedCommunity } from './0068-community_tables_public_key_length/FederatedCommunity'

View File

@ -0,0 +1,42 @@
/* MIGRATION TO CORRECT THE PUBLIC KEY LENGTHS
*
* This migration corrects the length of the saved public keys to 32 as this is the length it is generated for.
*/
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
/* eslint-disable @typescript-eslint/no-explicit-any */
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
// federated communities
await queryFn('DROP INDEX `public_api_key` ON `federated_communities`;')
await queryFn('UPDATE `federated_communities` SET `public_key` = UNHEX(public_key);')
await queryFn(
'ALTER TABLE `federated_communities` ADD COLUMN `public_key_new` binary(32) NOT NULL AFTER `public_key`;',
)
await queryFn('UPDATE `federated_communities` SET public_key_new = substring(public_key,1,32);')
await queryFn('ALTER TABLE `federated_communities` DROP COLUMN public_key;')
await queryFn('ALTER TABLE `federated_communities` RENAME COLUMN public_key_new TO public_key;')
await queryFn(
'ALTER TABLE `federated_communities` ADD CONSTRAINT `public_api_key` UNIQUE (public_key, api_version);',
)
// communities
await queryFn(
'ALTER TABLE `communities` ADD COLUMN `public_key_new` binary(32) NOT NULL AFTER `public_key`;',
)
await queryFn('UPDATE `communities` SET public_key_new = substring(public_key,1,32);')
await queryFn('ALTER TABLE `communities` DROP COLUMN public_key;')
await queryFn('ALTER TABLE `communities` RENAME COLUMN public_key_new TO public_key;')
}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
await queryFn(
'ALTER TABLE `federated_communities` MODIFY COLUMN `public_key` binary(64) NOT NULL;',
)
await queryFn(
'UPDATE `federated_communities` SET `public_key` = substring(HEX(public_key),1,64);',
)
await queryFn(
'ALTER TABLE `communities` MODIFY COLUMN `public_key` binary(64) NULL DEFAULT NULL;',
)
}

View File

@ -4,7 +4,7 @@ import dotenv from 'dotenv'
dotenv.config()
const constants = {
DB_VERSION: '0067-private_key_in_community_table',
DB_VERSION: '0068-community_tables_public_key_length',
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info
LOG_LEVEL: process.env.LOG_LEVEL || 'info',

View File

@ -97,7 +97,7 @@ export const startDHT = async (topic: string): Promise<void> => {
const variables = {
apiVersion: recApiVersion.api,
endPoint: recApiVersion.url,
publicKey: socket.remotePublicKey.toString('hex'),
publicKey: socket.remotePublicKey,
lastAnnouncedAt: new Date(),
}
logger.debug(`upsert with variables=${JSON.stringify(variables)}`)
@ -198,14 +198,14 @@ async function writeFederatedHomeCommunityEntries(pubKey: string): Promise<Commu
return comApi
})
try {
// first remove privious existing homeCommunity entries
// first remove previous existing homeCommunity entries
await DbFederatedCommunity.createQueryBuilder().delete().where({ foreign: false }).execute()
for (const homeApiVersion of homeApiVersions) {
const homeCom = DbFederatedCommunity.create()
homeCom.foreign = false
homeCom.apiVersion = homeApiVersion.api
homeCom.endPoint = homeApiVersion.url
homeCom.publicKey = Buffer.from(pubKey)
homeCom.publicKey = Buffer.from(pubKey, 'hex')
await DbFederatedCommunity.insert(homeCom)
logger.info(`federation home-community inserted successfully:`, homeApiVersion)
}

View File

@ -11,7 +11,7 @@ Decimal.set({
*/
const constants = {
DB_VERSION: '0067-private_key_in_community_table',
DB_VERSION: '0068-community_tables_public_key_length',
// DECAY_START_TIME: new Date('2021-05-13 17:46:31-0000'), // GMT+0
LOG4JS_CONFIG: 'log4js-config.json',
// default log level on production should be info