mostly update backend stuff

This commit is contained in:
einhorn_b 2024-01-12 15:55:24 +01:00
parent 0e91cd1579
commit c4c0c6680e
17 changed files with 283 additions and 36 deletions

View File

@ -0,0 +1,30 @@
import gql from 'graphql-tag'
export const allCommunities = gql`
query {
allCommunities {
id
foreign
url
publicKey
communityUuid
authenticatedAt
name
description
gmsApiKey
creationDate
createdAt
updatedAt
federatedCommunities {
id
apiVersion
endPoint
lastAnnouncedAt
verifiedAt
lastErrorAt
createdAt
updatedAt
}
}
}
`

View File

@ -1,17 +0,0 @@
import gql from 'graphql-tag'
export const getCommunities = gql`
query {
getCommunities {
id
foreign
publicKey
url
lastAnnouncedAt
verifiedAt
lastErrorAt
createdAt
updatedAt
}
}
`

View File

@ -7,7 +7,7 @@
icon="arrow-clockwise"
font-scale="2"
:animation="animation"
@click="$apollo.queries.GetCommunities.refresh()"
@click="$apollo.queries.allCommunities.refresh()"
data-test="federation-communities-refresh-btn"
></b-icon>
</b-button>
@ -30,9 +30,9 @@
</div>
</template>
<script>
import { getCommunities } from '@/graphql/getCommunities'
import { allCommunities } from '@/graphql/allCommunities'
import FederationVisualizeItem from '../components/Fedaration/FederationVisualizeItem.vue'
import FederationVisualizeItem from '../components/Federation/FederationVisualizeItem.vue'
export default {
name: 'FederationVisualize',
@ -48,17 +48,17 @@ export default {
},
computed: {
animation() {
return this.$apollo.queries.GetCommunities.loading ? 'spin' : ''
return this.$apollo.queries.allCommunities.loading ? 'spin' : ''
},
},
apollo: {
GetCommunities: {
allCommunities: {
fetchPolicy: 'network-only',
query() {
return getCommunities
return allCommunities
},
update({ getCommunities }) {
this.communities = getCommunities
update({ allCommunities }) {
this.communities = allCommunities
},
error({ message }) {
this.toastError(message)

View File

@ -12,7 +12,7 @@ Decimal.set({
})
const constants = {
DB_VERSION: '0081-introduce_gms_registration',
DB_VERSION: '0082-join_community_federated_communities',
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

@ -1,6 +1,9 @@
import { Community as DbCommunity } from '@entity/Community'
import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity'
import { ObjectType, Field, Int } from 'type-graphql'
import { FederatedCommunity } from './FederatedCommunity'
@ObjectType()
export class Community {
constructor(dbCom: DbCommunity) {
@ -8,10 +11,20 @@ export class Community {
this.foreign = dbCom.foreign
this.name = dbCom.name
this.description = dbCom.description
this.gmsApiKey = dbCom.gmsApiKey
this.url = dbCom.url
this.publicKey = dbCom.publicKey.toString('hex')
this.communityUuid = dbCom.communityUuid
this.creationDate = dbCom.creationDate
this.createdAt = dbCom.createdAt
this.updatedAt = dbCom.updatedAt
this.uuid = dbCom.communityUuid
this.authenticatedAt = dbCom.authenticatedAt
if (dbCom.federatedCommunities) {
this.federatedCommunities = dbCom.federatedCommunities.map(
(federatedCom: DbFederatedCommunity) => new FederatedCommunity(federatedCom),
)
}
}
@Field(() => Int)
@ -26,15 +39,33 @@ export class Community {
@Field(() => String, { nullable: true })
description: string | null
@Field(() => String, { nullable: true })
gmsApiKey: string | null
@Field(() => String)
url: string
@Field(() => String)
publicKey: string
@Field(() => String, { nullable: true })
communityUuid: string | null
@Field(() => Date, { nullable: true })
creationDate: Date | null
@Field(() => Date, { nullable: true })
createdAt: Date | null
@Field(() => Date, { nullable: true })
updatedAt: Date | null
@Field(() => String, { nullable: true })
uuid: string | null
@Field(() => Date, { nullable: true })
authenticatedAt: Date | null
@Field(() => [FederatedCommunity], { nullable: true })
federatedCommunities: FederatedCommunity[] | null
}

View File

@ -6,9 +6,9 @@ export class FederatedCommunity {
constructor(dbCom: DbFederatedCommunity) {
this.id = dbCom.id
this.foreign = dbCom.foreign
this.publicKey = dbCom.publicKey.toString()
this.url =
(dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/') + dbCom.apiVersion
this.publicKey = dbCom.publicKey.toString('hex')
this.apiVersion = dbCom.apiVersion
this.endPoint = dbCom.endPoint.endsWith('/') ? dbCom.endPoint : dbCom.endPoint + '/'
this.lastAnnouncedAt = dbCom.lastAnnouncedAt
this.verifiedAt = dbCom.verifiedAt
this.lastErrorAt = dbCom.lastErrorAt
@ -26,7 +26,10 @@ export class FederatedCommunity {
publicKey: string
@Field(() => String)
url: string
apiVersion: string
@Field(() => String)
endPoint: string
@Field(() => Date, { nullable: true })
lastAnnouncedAt: Date | null

View File

@ -1,15 +1,16 @@
import { IsNull, Not } from '@dbTools/typeorm'
import { Community as DbCommunity } from '@entity/Community'
import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity'
import { Resolver, Query, Authorized, Arg } from 'type-graphql'
import { Resolver, Query, Authorized, Arg, Args } from 'type-graphql'
import { Paginated } from '@arg/Paginated'
import { Community } from '@model/Community'
import { FederatedCommunity } from '@model/FederatedCommunity'
import { RIGHTS } from '@/auth/RIGHTS'
import { LogError } from '@/server/LogError'
import { getCommunity } from './util/communities'
import { getAllCommunities, getCommunity } from './util/communities'
@Resolver()
export class CommunityResolver {
@ -28,6 +29,12 @@ export class CommunityResolver {
)
}
@Authorized([RIGHTS.COMMUNITIES])
@Query(() => [Community])
async allCommunities(@Args() paginated: Paginated): Promise<Community[]> {
return (await getAllCommunities(paginated)).map((dbCom) => new Community(dbCom))
}
@Authorized([RIGHTS.COMMUNITIES])
@Query(() => [Community])
async communities(): Promise<Community[]> {

View File

@ -1,4 +1,11 @@
import { Community as DbCommunity } from '@entity/Community'
import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity'
import { Paginated } from '@arg/Paginated'
import { Order } from '@/graphql/enum/Order'
import { LogError } from '@/server/LogError'
import { Connection } from '@/typeorm/connection'
export async function isHomeCommunity(communityIdentifier: string): Promise<boolean> {
const homeCommunity = await DbCommunity.findOne({
@ -63,3 +70,55 @@ export async function getCommunity(communityUuid: string): Promise<DbCommunity |
where: [{ communityUuid }],
})
}
/**
* Simulate RIGHT Join between Communities and Federated Communities
* select *
* Community as c
* RIGHT JOIN FederatedCommunity as f
* ON(c.public_key = f.public_key)
* Typeorm don't has right joins
* @returns
*/
export async function getAllCommunities({
pageSize = 25,
currentPage = 1,
}: Paginated): Promise<DbCommunity[]> {
const connection = await Connection.getInstance()
if (!connection) {
throw new LogError('Cannot connect to db')
}
// foreign: 'ASC',
// createdAt: 'DESC',
// lastAnnouncedAt: 'DESC',
const result = await connection
.getRepository(DbFederatedCommunity)
.createQueryBuilder('federatedCommunity')
.leftJoinAndSelect('federatedCommunity.community', 'community')
.orderBy('federatedCommunity.foreign', 'ASC')
.addOrderBy('federatedCommunity.createdAt', 'DESC')
.addOrderBy('federatedCommunity.lastAnnouncedAt', 'DESC')
.skip((currentPage - 1) * pageSize * 3)
.take(pageSize * 3)
.getManyAndCount()
const communityMap = new Map<string, DbCommunity>()
result[0].forEach((value: DbFederatedCommunity) => {
const publicKeyHex = value.publicKey.toString('hex')
if (!communityMap.has(value.publicKey.toString('hex'))) {
let community: DbCommunity = DbCommunity.create()
if (value.community) {
community = value.community
}
if (!community.federatedCommunities) {
community.federatedCommunities = []
}
communityMap.set(publicKeyHex, community)
}
const community = communityMap.get(publicKeyHex)
if (!community?.federatedCommunities) {
throw new LogError('missing community after set it into map', publicKeyHex)
}
community.federatedCommunities.push(value)
})
return Array.from(communityMap.values())
}

View File

@ -0,0 +1,73 @@
import {
BaseEntity,
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
JoinColumn,
} from 'typeorm'
import { FederatedCommunity } from '../FederatedCommunity'
@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
@Column({ name: 'gms_api_key', type: 'varchar', length: 512, nullable: true, default: null })
gmsApiKey: string | 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
@OneToMany(() => FederatedCommunity, (federatedCommunity) => federatedCommunity.community)
@JoinColumn({ name: 'public_key', referencedColumnName: 'publicKey' })
federatedCommunities?: FederatedCommunity[]
}

View File

@ -0,0 +1,58 @@
import {
BaseEntity,
Entity,
PrimaryGeneratedColumn,
Column,
CreateDateColumn,
UpdateDateColumn,
ManyToOne,
JoinColumn,
} from 'typeorm'
import { Community } from '../Community'
@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
@ManyToOne(() => Community, (community) => community.federatedCommunities) // Assuming you have a User entity with 'accounts' relation
@JoinColumn({ name: 'public_key', referencedColumnName: 'publicKey' })
community?: Community
}

View File

@ -1 +1 @@
export { Community } from './0081-introduce_gms_registration/Community'
export { Community } from './0082-join_community_federated_communities/Community'

View File

@ -1 +1 @@
export { FederatedCommunity } from './0068-community_tables_public_key_length/FederatedCommunity'
export { FederatedCommunity } from './0082-join_community_federated_communities/FederatedCommunity'

View File

@ -0,0 +1,3 @@
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {}
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {}

View File

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

View File

@ -10,7 +10,7 @@ Decimal.set({
})
const constants = {
DB_VERSION: '0081-introduce_gms_registration',
DB_VERSION: '0082-join_community_federated_communities',
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