mirror of
https://github.com/IT4Change/gradido.git
synced 2026-02-06 09:56:05 +00:00
refactor community, rights and allow input community/user in frontend gdd send form
This commit is contained in:
parent
097fcd7103
commit
bf33cf9341
@ -8,7 +8,7 @@ export const updateHomeCommunity = gql`
|
|||||||
location: $location
|
location: $location
|
||||||
hieroTopicId: $hieroTopicId
|
hieroTopicId: $hieroTopicId
|
||||||
) {
|
) {
|
||||||
id
|
uuid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|||||||
@ -5,8 +5,6 @@ export const ADMIN_RIGHTS = [
|
|||||||
RIGHTS.DELETE_USER,
|
RIGHTS.DELETE_USER,
|
||||||
RIGHTS.UNDELETE_USER,
|
RIGHTS.UNDELETE_USER,
|
||||||
RIGHTS.COMMUNITY_UPDATE,
|
RIGHTS.COMMUNITY_UPDATE,
|
||||||
RIGHTS.COMMUNITY_BY_UUID,
|
RIGHTS.COMMUNITY_WITH_API_KEYS,
|
||||||
RIGHTS.COMMUNITY_BY_IDENTIFIER,
|
|
||||||
RIGHTS.HOME_COMMUNITY,
|
|
||||||
RIGHTS.PROJECT_BRANDING_MUTATE,
|
RIGHTS.PROJECT_BRANDING_MUTATE,
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
import { RIGHTS } from './RIGHTS'
|
import { RIGHTS } from './RIGHTS'
|
||||||
|
|
||||||
export const DLT_CONNECTOR_RIGHTS = [RIGHTS.COMMUNITY_BY_IDENTIFIER, RIGHTS.HOME_COMMUNITY]
|
export const DLT_CONNECTOR_RIGHTS = [RIGHTS.COMMUNITIES, RIGHTS.COMMUNITY_UPDATE]
|
||||||
|
|||||||
@ -35,6 +35,7 @@ export enum RIGHTS {
|
|||||||
UPDATE_CONTRIBUTION = 'UPDATE_CONTRIBUTION',
|
UPDATE_CONTRIBUTION = 'UPDATE_CONTRIBUTION',
|
||||||
LIST_CONTRIBUTION_LINKS = 'LIST_CONTRIBUTION_LINKS',
|
LIST_CONTRIBUTION_LINKS = 'LIST_CONTRIBUTION_LINKS',
|
||||||
COMMUNITY_STATISTICS = 'COMMUNITY_STATISTICS',
|
COMMUNITY_STATISTICS = 'COMMUNITY_STATISTICS',
|
||||||
|
COMMUNITY_STATUS = 'COMMUNITY_STATUS',
|
||||||
SEARCH_ADMIN_USERS = 'SEARCH_ADMIN_USERS',
|
SEARCH_ADMIN_USERS = 'SEARCH_ADMIN_USERS',
|
||||||
CREATE_CONTRIBUTION_MESSAGE = 'CREATE_CONTRIBUTION_MESSAGE',
|
CREATE_CONTRIBUTION_MESSAGE = 'CREATE_CONTRIBUTION_MESSAGE',
|
||||||
LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES',
|
LIST_ALL_CONTRIBUTION_MESSAGES = 'LIST_ALL_CONTRIBUTION_MESSAGES',
|
||||||
@ -69,9 +70,7 @@ export enum RIGHTS {
|
|||||||
SET_USER_ROLE = 'SET_USER_ROLE',
|
SET_USER_ROLE = 'SET_USER_ROLE',
|
||||||
DELETE_USER = 'DELETE_USER',
|
DELETE_USER = 'DELETE_USER',
|
||||||
UNDELETE_USER = 'UNDELETE_USER',
|
UNDELETE_USER = 'UNDELETE_USER',
|
||||||
COMMUNITY_BY_UUID = 'COMMUNITY_BY_UUID',
|
|
||||||
COMMUNITY_BY_IDENTIFIER = 'COMMUNITY_BY_IDENTIFIER',
|
|
||||||
HOME_COMMUNITY = 'HOME_COMMUNITY',
|
|
||||||
COMMUNITY_UPDATE = 'COMMUNITY_UPDATE',
|
COMMUNITY_UPDATE = 'COMMUNITY_UPDATE',
|
||||||
|
COMMUNITY_WITH_API_KEYS = 'COMMUNITY_WITH_API_KEYS',
|
||||||
PROJECT_BRANDING_MUTATE = 'PROJECT_BRANDING_MUTATE',
|
PROJECT_BRANDING_MUTATE = 'PROJECT_BRANDING_MUTATE',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ export const USER_RIGHTS = [
|
|||||||
RIGHTS.SEARCH_ADMIN_USERS,
|
RIGHTS.SEARCH_ADMIN_USERS,
|
||||||
RIGHTS.LIST_CONTRIBUTION_LINKS,
|
RIGHTS.LIST_CONTRIBUTION_LINKS,
|
||||||
RIGHTS.COMMUNITY_STATISTICS,
|
RIGHTS.COMMUNITY_STATISTICS,
|
||||||
|
RIGHTS.COMMUNITY_STATUS,
|
||||||
RIGHTS.CREATE_CONTRIBUTION_MESSAGE,
|
RIGHTS.CREATE_CONTRIBUTION_MESSAGE,
|
||||||
RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES,
|
RIGHTS.LIST_ALL_CONTRIBUTION_MESSAGES,
|
||||||
RIGHTS.OPEN_CREATIONS,
|
RIGHTS.OPEN_CREATIONS,
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { FederationClient as V1_0_FederationClient } from '@/federation/client/1
|
|||||||
import { FederationClient as V1_1_FederationClient } from '@/federation/client/1_1/FederationClient'
|
import { FederationClient as V1_1_FederationClient } from '@/federation/client/1_1/FederationClient'
|
||||||
import { ApiVersionType, ensureUrlEndsWithSlash } from 'core'
|
import { ApiVersionType, ensureUrlEndsWithSlash } from 'core'
|
||||||
|
|
||||||
type FederationClient = V1_0_FederationClient | V1_1_FederationClient
|
export type FederationClient = V1_0_FederationClient | V1_1_FederationClient
|
||||||
|
|
||||||
interface FederationClientInstance {
|
interface FederationClientInstance {
|
||||||
id: number
|
id: number
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export class UserArgs {
|
|||||||
@IsString()
|
@IsString()
|
||||||
identifier: string
|
identifier: string
|
||||||
|
|
||||||
@Field()
|
@Field({ nullable: true })
|
||||||
@IsString()
|
@IsString()
|
||||||
communityIdentifier: string
|
communityIdentifier?: string
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,6 @@ export class AdminCommunityView {
|
|||||||
this.updatedAt = dbCom.updatedAt
|
this.updatedAt = dbCom.updatedAt
|
||||||
this.uuid = dbCom.communityUuid
|
this.uuid = dbCom.communityUuid
|
||||||
this.authenticatedAt = dbCom.authenticatedAt
|
this.authenticatedAt = dbCom.authenticatedAt
|
||||||
this.gmsApiKey = dbCom.gmsApiKey
|
|
||||||
this.hieroTopicId = dbCom.hieroTopicId
|
this.hieroTopicId = dbCom.hieroTopicId
|
||||||
if (dbCom.location) {
|
if (dbCom.location) {
|
||||||
this.location = Point2Location(dbCom.location as Point)
|
this.location = Point2Location(dbCom.location as Point)
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export class Community {
|
|||||||
this.creationDate = dbCom.creationDate
|
this.creationDate = dbCom.creationDate
|
||||||
this.uuid = dbCom.communityUuid
|
this.uuid = dbCom.communityUuid
|
||||||
this.authenticatedAt = dbCom.authenticatedAt
|
this.authenticatedAt = dbCom.authenticatedAt
|
||||||
this.gmsApiKey = dbCom.gmsApiKey
|
// this.gmsApiKey = dbCom.gmsApiKey //
|
||||||
this.hieroTopicId = dbCom.hieroTopicId
|
this.hieroTopicId = dbCom.hieroTopicId
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,8 +40,9 @@ export class Community {
|
|||||||
@Field(() => Date, { nullable: true })
|
@Field(() => Date, { nullable: true })
|
||||||
authenticatedAt: Date | null
|
authenticatedAt: Date | null
|
||||||
|
|
||||||
@Field(() => String, { nullable: true })
|
// gms api key should only seen by admins, they can use AdminCommunityView
|
||||||
gmsApiKey: string | null
|
// @Field(() => String, { nullable: true })
|
||||||
|
// gmsApiKey: string | null
|
||||||
|
|
||||||
@Field(() => String, { nullable: true })
|
@Field(() => String, { nullable: true })
|
||||||
hieroTopicId: string | null
|
hieroTopicId: string | null
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ApolloServerTestClient } from 'apollo-server-testing'
|
import { ApolloServerTestClient } from 'apollo-server-testing'
|
||||||
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity } from 'database'
|
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity, getHomeCommunity } from 'database'
|
||||||
import { GraphQLError } from 'graphql/error/GraphQLError'
|
import { GraphQLError } from 'graphql/error/GraphQLError'
|
||||||
import { DataSource } from 'typeorm'
|
import { DataSource } from 'typeorm'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
@ -11,18 +11,20 @@ import { userFactory } from '@/seeds/factory/user'
|
|||||||
import { login, updateHomeCommunityQuery } from '@/seeds/graphql/mutations'
|
import { login, updateHomeCommunityQuery } from '@/seeds/graphql/mutations'
|
||||||
import {
|
import {
|
||||||
allCommunities,
|
allCommunities,
|
||||||
communitiesQuery,
|
|
||||||
getCommunities,
|
|
||||||
getCommunityByIdentifierQuery,
|
getCommunityByIdentifierQuery,
|
||||||
getHomeCommunityQuery,
|
getHomeCommunityQuery,
|
||||||
|
reachableCommunities,
|
||||||
} from '@/seeds/graphql/queries'
|
} from '@/seeds/graphql/queries'
|
||||||
import { peterLustig } from '@/seeds/users/peter-lustig'
|
import { peterLustig } from '@/seeds/users/peter-lustig'
|
||||||
|
import { createCommunity, createAuthenticatedForeignCommunity } from 'database/src/seeds/community'
|
||||||
|
|
||||||
import { getLogger } from 'config-schema/test/testSetup'
|
import { getLogger } from 'config-schema/test/testSetup'
|
||||||
import { getCommunityByUuid } from './util/communities'
|
import { getCommunityByUuid } from './util/communities'
|
||||||
|
import { CONFIG } from '@/config'
|
||||||
|
|
||||||
jest.mock('@/password/EncryptorUtils')
|
jest.mock('@/password/EncryptorUtils')
|
||||||
|
|
||||||
|
CONFIG.FEDERATION_VALIDATE_COMMUNITY_TIMER = 1000
|
||||||
|
|
||||||
// to do: We need a setup for the tests that closes the connection
|
// to do: We need a setup for the tests that closes the connection
|
||||||
let mutate: ApolloServerTestClient['mutate']
|
let mutate: ApolloServerTestClient['mutate']
|
||||||
@ -46,11 +48,10 @@ beforeAll(async () => {
|
|||||||
mutate = testEnv.mutate
|
mutate = testEnv.mutate
|
||||||
query = testEnv.query
|
query = testEnv.query
|
||||||
con = testEnv.con
|
con = testEnv.con
|
||||||
await DbFederatedCommunity.clear()
|
await cleanDB()
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await cleanDB()
|
|
||||||
await con.destroy()
|
await con.destroy()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -109,7 +110,7 @@ const ed25519KeyPairStaticHex = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
describe('CommunityResolver', () => {
|
describe('CommunityResolver', () => {
|
||||||
describe('getCommunities', () => {
|
describe('allCommunities for admin', () => {
|
||||||
let homeCom1: DbFederatedCommunity
|
let homeCom1: DbFederatedCommunity
|
||||||
let homeCom2: DbFederatedCommunity
|
let homeCom2: DbFederatedCommunity
|
||||||
let homeCom3: DbFederatedCommunity
|
let homeCom3: DbFederatedCommunity
|
||||||
@ -117,23 +118,30 @@ describe('CommunityResolver', () => {
|
|||||||
let foreignCom2: DbFederatedCommunity
|
let foreignCom2: DbFederatedCommunity
|
||||||
let foreignCom3: DbFederatedCommunity
|
let foreignCom3: DbFederatedCommunity
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
// create admin and login as admin
|
||||||
|
await userFactory(testEnv, peterLustig)
|
||||||
|
await mutate({ mutation: login, variables: peterLoginData })
|
||||||
|
})
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await cleanDB()
|
||||||
|
})
|
||||||
|
|
||||||
describe('with empty list', () => {
|
describe('with empty list', () => {
|
||||||
it('returns no community entry', async () => {
|
it('returns no community entry', async () => {
|
||||||
// const result: Community[] = await query({ query: getCommunities })
|
// const result: Community[] = await query({ query: getCommunities })
|
||||||
// expect(result.length).toEqual(0)
|
// expect(result.length).toEqual(0)
|
||||||
await expect(query({ query: getCommunities })).resolves.toMatchObject({
|
await expect(query({ query: allCommunities })).resolves.toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
getCommunities: [],
|
allCommunities: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('only home-communities entries', () => {
|
describe('only home-community entries (different apis)', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await cleanDB()
|
|
||||||
jest.clearAllMocks()
|
|
||||||
|
|
||||||
homeCom1 = DbFederatedCommunity.create()
|
homeCom1 = DbFederatedCommunity.create()
|
||||||
homeCom1.foreign = false
|
homeCom1.foreign = false
|
||||||
homeCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
homeCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
||||||
@ -144,7 +152,7 @@ describe('CommunityResolver', () => {
|
|||||||
|
|
||||||
homeCom2 = DbFederatedCommunity.create()
|
homeCom2 = DbFederatedCommunity.create()
|
||||||
homeCom2.foreign = false
|
homeCom2.foreign = false
|
||||||
homeCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[1].public, 'hex')
|
homeCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
||||||
homeCom2.apiVersion = '1_1'
|
homeCom2.apiVersion = '1_1'
|
||||||
homeCom2.endPoint = 'http://localhost/api'
|
homeCom2.endPoint = 'http://localhost/api'
|
||||||
homeCom2.createdAt = new Date()
|
homeCom2.createdAt = new Date()
|
||||||
@ -152,170 +160,67 @@ describe('CommunityResolver', () => {
|
|||||||
|
|
||||||
homeCom3 = DbFederatedCommunity.create()
|
homeCom3 = DbFederatedCommunity.create()
|
||||||
homeCom3.foreign = false
|
homeCom3.foreign = false
|
||||||
homeCom3.publicKey = Buffer.from(ed25519KeyPairStaticHex[2].public, 'hex')
|
homeCom3.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
||||||
homeCom3.apiVersion = '2_0'
|
homeCom3.apiVersion = '2_0'
|
||||||
homeCom3.endPoint = 'http://localhost/api'
|
homeCom3.endPoint = 'http://localhost/api'
|
||||||
homeCom3.createdAt = new Date()
|
homeCom3.createdAt = new Date()
|
||||||
await DbFederatedCommunity.insert(homeCom3)
|
await DbFederatedCommunity.insert(homeCom3)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns 3 home-community entries', async () => {
|
it('returns only home-community entries', async () => {
|
||||||
await expect(query({ query: getCommunities })).resolves.toMatchObject({
|
await expect(query({ query: allCommunities })).resolves.toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
getCommunities: [
|
allCommunities: [
|
||||||
{
|
{
|
||||||
id: 3,
|
foreign: false,
|
||||||
foreign: homeCom3.foreign,
|
url: 'http://localhost',
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[2].public),
|
|
||||||
endPoint: expect.stringMatching('http://localhost/api/'),
|
|
||||||
apiVersion: '2_0',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: homeCom3.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
foreign: homeCom2.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[1].public),
|
|
||||||
endPoint: expect.stringMatching('http://localhost/api/'),
|
|
||||||
apiVersion: '1_1',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: homeCom2.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
foreign: homeCom1.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[0].public),
|
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[0].public),
|
||||||
endPoint: expect.stringMatching('http://localhost/api/'),
|
authenticatedAt: null,
|
||||||
apiVersion: '1_0',
|
createdAt: null,
|
||||||
lastAnnouncedAt: null,
|
creationDate: null,
|
||||||
verifiedAt: null,
|
description: null,
|
||||||
lastErrorAt: null,
|
gmsApiKey: null,
|
||||||
createdAt: homeCom1.createdAt.toISOString(),
|
name: null,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
|
uuid: null,
|
||||||
|
federatedCommunities: [
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
apiVersion: '2_0',
|
||||||
|
endPoint: 'http://localhost/api/',
|
||||||
|
createdAt: homeCom3.createdAt.toISOString(),
|
||||||
|
lastAnnouncedAt: null,
|
||||||
|
lastErrorAt: null,
|
||||||
|
updatedAt: null,
|
||||||
|
verifiedAt: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
apiVersion: '1_1',
|
||||||
|
endPoint: 'http://localhost/api/',
|
||||||
|
createdAt: homeCom2.createdAt.toISOString(),
|
||||||
|
lastAnnouncedAt: null,
|
||||||
|
lastErrorAt: null,
|
||||||
|
updatedAt: null,
|
||||||
|
verifiedAt: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
apiVersion: '1_0',
|
||||||
|
endPoint: 'http://localhost/api/',
|
||||||
|
createdAt: homeCom1.createdAt.toISOString(),
|
||||||
|
lastAnnouncedAt: null,
|
||||||
|
lastErrorAt: null,
|
||||||
|
updatedAt: null,
|
||||||
|
verifiedAt: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('plus foreign-communities entries', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
|
|
||||||
foreignCom1 = DbFederatedCommunity.create()
|
|
||||||
foreignCom1.foreign = true
|
|
||||||
foreignCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[3].public, 'hex')
|
|
||||||
foreignCom1.apiVersion = '1_0'
|
|
||||||
foreignCom1.endPoint = 'http://remotehost/api'
|
|
||||||
foreignCom1.createdAt = new Date()
|
|
||||||
await DbFederatedCommunity.insert(foreignCom1)
|
|
||||||
|
|
||||||
foreignCom2 = DbFederatedCommunity.create()
|
|
||||||
foreignCom2.foreign = true
|
|
||||||
foreignCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[4].public, 'hex')
|
|
||||||
foreignCom2.apiVersion = '1_1'
|
|
||||||
foreignCom2.endPoint = 'http://remotehost/api'
|
|
||||||
foreignCom2.createdAt = new Date()
|
|
||||||
await DbFederatedCommunity.insert(foreignCom2)
|
|
||||||
|
|
||||||
foreignCom3 = DbFederatedCommunity.create()
|
|
||||||
foreignCom3.foreign = true
|
|
||||||
foreignCom3.publicKey = Buffer.from(ed25519KeyPairStaticHex[5].public, 'hex')
|
|
||||||
foreignCom3.apiVersion = '2_0'
|
|
||||||
foreignCom3.endPoint = 'http://remotehost/api'
|
|
||||||
foreignCom3.createdAt = new Date()
|
|
||||||
await DbFederatedCommunity.insert(foreignCom3)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('returns 3 home community and 3 foreign community entries', async () => {
|
|
||||||
await expect(query({ query: getCommunities })).resolves.toMatchObject({
|
|
||||||
data: {
|
|
||||||
getCommunities: [
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
foreign: homeCom3.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[2].public),
|
|
||||||
endPoint: expect.stringMatching('http://localhost/api/'),
|
|
||||||
apiVersion: '2_0',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: homeCom3.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
foreign: homeCom2.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[1].public),
|
|
||||||
endPoint: expect.stringMatching('http://localhost/api/'),
|
|
||||||
apiVersion: '1_1',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: homeCom2.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
foreign: homeCom1.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[0].public),
|
|
||||||
endPoint: expect.stringMatching('http://localhost/api/'),
|
|
||||||
apiVersion: '1_0',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: homeCom1.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 6,
|
|
||||||
foreign: foreignCom3.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[5].public),
|
|
||||||
endPoint: expect.stringMatching('http://remotehost/api/'),
|
|
||||||
apiVersion: '2_0',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: foreignCom3.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
foreign: foreignCom2.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[4].public),
|
|
||||||
endPoint: expect.stringMatching('http://remotehost/api/'),
|
|
||||||
apiVersion: '1_1',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: foreignCom2.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
foreign: foreignCom1.foreign,
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[3].public),
|
|
||||||
endPoint: expect.stringMatching('http://remotehost/api/'),
|
|
||||||
apiVersion: '1_0',
|
|
||||||
lastAnnouncedAt: null,
|
|
||||||
verifiedAt: null,
|
|
||||||
lastErrorAt: null,
|
|
||||||
createdAt: foreignCom1.createdAt.toISOString(),
|
|
||||||
updatedAt: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('with 6 federated community entries', () => {
|
describe('with 6 federated community entries', () => {
|
||||||
let comHomeCom1: DbCommunity
|
let comHomeCom1: DbCommunity
|
||||||
let comForeignCom1: DbCommunity
|
let comForeignCom1: DbCommunity
|
||||||
@ -323,7 +228,6 @@ describe('CommunityResolver', () => {
|
|||||||
let foreignCom4: DbFederatedCommunity
|
let foreignCom4: DbFederatedCommunity
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
|
||||||
comHomeCom1 = DbCommunity.create()
|
comHomeCom1 = DbCommunity.create()
|
||||||
comHomeCom1.foreign = false
|
comHomeCom1.foreign = false
|
||||||
comHomeCom1.url = 'http://localhost'
|
comHomeCom1.url = 'http://localhost'
|
||||||
@ -360,6 +264,30 @@ describe('CommunityResolver', () => {
|
|||||||
comForeignCom2.creationDate = new Date()
|
comForeignCom2.creationDate = new Date()
|
||||||
await DbCommunity.insert(comForeignCom2)
|
await DbCommunity.insert(comForeignCom2)
|
||||||
|
|
||||||
|
foreignCom1 = DbFederatedCommunity.create()
|
||||||
|
foreignCom1.foreign = true
|
||||||
|
foreignCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[3].public, 'hex')
|
||||||
|
foreignCom1.apiVersion = '1_0'
|
||||||
|
foreignCom1.endPoint = 'http://remotehost/api'
|
||||||
|
foreignCom1.createdAt = new Date()
|
||||||
|
await DbFederatedCommunity.insert(foreignCom1)
|
||||||
|
|
||||||
|
foreignCom2 = DbFederatedCommunity.create()
|
||||||
|
foreignCom2.foreign = true
|
||||||
|
foreignCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[4].public, 'hex')
|
||||||
|
foreignCom2.apiVersion = '1_1'
|
||||||
|
foreignCom2.endPoint = 'http://remotehost/api'
|
||||||
|
foreignCom2.createdAt = new Date()
|
||||||
|
await DbFederatedCommunity.insert(foreignCom2)
|
||||||
|
|
||||||
|
foreignCom3 = DbFederatedCommunity.create()
|
||||||
|
foreignCom3.foreign = true
|
||||||
|
foreignCom3.publicKey = Buffer.from(ed25519KeyPairStaticHex[5].public, 'hex')
|
||||||
|
foreignCom3.apiVersion = '2_0'
|
||||||
|
foreignCom3.endPoint = 'http://remotehost/api'
|
||||||
|
foreignCom3.createdAt = new Date()
|
||||||
|
await DbFederatedCommunity.insert(foreignCom3)
|
||||||
|
|
||||||
foreignCom4 = DbFederatedCommunity.create()
|
foreignCom4 = DbFederatedCommunity.create()
|
||||||
foreignCom4.foreign = true
|
foreignCom4.foreign = true
|
||||||
foreignCom4.publicKey = Buffer.from(ed25519KeyPairStaticHex[5].public, 'hex')
|
foreignCom4.publicKey = Buffer.from(ed25519KeyPairStaticHex[5].public, 'hex')
|
||||||
@ -376,15 +304,15 @@ describe('CommunityResolver', () => {
|
|||||||
{
|
{
|
||||||
foreign: false,
|
foreign: false,
|
||||||
url: 'http://localhost',
|
url: 'http://localhost',
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[2].public),
|
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[0].public),
|
||||||
authenticatedAt: null,
|
authenticatedAt: comHomeCom1.authenticatedAt?.toISOString(),
|
||||||
createdAt: null,
|
createdAt: comHomeCom1.createdAt.toISOString(),
|
||||||
creationDate: null,
|
creationDate: comHomeCom1.creationDate?.toISOString(),
|
||||||
description: null,
|
description: comHomeCom1.description,
|
||||||
gmsApiKey: null,
|
gmsApiKey: null,
|
||||||
name: null,
|
name: comHomeCom1.name,
|
||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
uuid: null,
|
uuid: comHomeCom1.communityUuid,
|
||||||
federatedCommunities: [
|
federatedCommunities: [
|
||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
@ -396,21 +324,6 @@ describe('CommunityResolver', () => {
|
|||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
verifiedAt: null,
|
verifiedAt: null,
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
foreign: false,
|
|
||||||
url: 'http://localhost',
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[1].public),
|
|
||||||
authenticatedAt: null,
|
|
||||||
createdAt: null,
|
|
||||||
creationDate: null,
|
|
||||||
description: null,
|
|
||||||
gmsApiKey: null,
|
|
||||||
name: null,
|
|
||||||
updatedAt: null,
|
|
||||||
uuid: null,
|
|
||||||
federatedCommunities: [
|
|
||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
apiVersion: '1_1',
|
apiVersion: '1_1',
|
||||||
@ -421,21 +334,6 @@ describe('CommunityResolver', () => {
|
|||||||
updatedAt: null,
|
updatedAt: null,
|
||||||
verifiedAt: null,
|
verifiedAt: null,
|
||||||
},
|
},
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
foreign: false,
|
|
||||||
url: 'http://localhost',
|
|
||||||
publicKey: expect.stringMatching(ed25519KeyPairStaticHex[0].public),
|
|
||||||
authenticatedAt: comHomeCom1.authenticatedAt?.toISOString(),
|
|
||||||
createdAt: comHomeCom1.createdAt.toISOString(),
|
|
||||||
creationDate: comHomeCom1.creationDate?.toISOString(),
|
|
||||||
description: comHomeCom1.description,
|
|
||||||
gmsApiKey: null,
|
|
||||||
name: comHomeCom1.name,
|
|
||||||
updatedAt: null,
|
|
||||||
uuid: comHomeCom1.communityUuid,
|
|
||||||
federatedCommunities: [
|
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
apiVersion: '1_0',
|
apiVersion: '1_0',
|
||||||
@ -540,23 +438,20 @@ describe('CommunityResolver', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('communities', () => {
|
describe('reachableCommunities', () => {
|
||||||
let homeCom1: DbCommunity
|
let homeCom1: DbCommunity
|
||||||
let foreignCom1: DbCommunity
|
let foreignCom1: DbCommunity
|
||||||
let foreignCom2: DbCommunity
|
let foreignCom2: DbCommunity
|
||||||
|
|
||||||
describe('with empty list', () => {
|
afterAll(async () => {
|
||||||
beforeEach(async () => {
|
await DbCommunity.clear()
|
||||||
await cleanDB()
|
})
|
||||||
jest.clearAllMocks()
|
|
||||||
})
|
|
||||||
|
|
||||||
|
describe('with empty list', () => {
|
||||||
it('returns no community entry', async () => {
|
it('returns no community entry', async () => {
|
||||||
// const result: Community[] = await query({ query: getCommunities })
|
await expect(query({ query: reachableCommunities })).resolves.toMatchObject({
|
||||||
// expect(result.length).toEqual(0)
|
|
||||||
await expect(query({ query: communitiesQuery })).resolves.toMatchObject({
|
|
||||||
data: {
|
data: {
|
||||||
communities: [],
|
reachableCommunities: [],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -564,35 +459,20 @@ describe('CommunityResolver', () => {
|
|||||||
|
|
||||||
describe('with one home-community entry', () => {
|
describe('with one home-community entry', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await cleanDB()
|
homeCom1 = await createCommunity(false, false)
|
||||||
jest.clearAllMocks()
|
|
||||||
|
|
||||||
homeCom1 = DbCommunity.create()
|
|
||||||
homeCom1.foreign = false
|
|
||||||
homeCom1.url = 'http://localhost/api'
|
|
||||||
homeCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
|
||||||
homeCom1.privateKey = Buffer.from(ed25519KeyPairStaticHex[0].private, 'hex')
|
|
||||||
homeCom1.communityUuid = 'HomeCom-UUID'
|
|
||||||
homeCom1.authenticatedAt = new Date()
|
|
||||||
homeCom1.name = 'HomeCommunity-name'
|
|
||||||
homeCom1.description = 'HomeCommunity-description'
|
|
||||||
homeCom1.creationDate = new Date()
|
|
||||||
await DbCommunity.insert(homeCom1)
|
await DbCommunity.insert(homeCom1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns 1 home-community entry', async () => {
|
it('returns 1 home-community entry', async () => {
|
||||||
await expect(query({ query: communitiesQuery })).resolves.toMatchObject({
|
await expect(query({ query: reachableCommunities })).resolves.toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
communities: [
|
reachableCommunities: [
|
||||||
{
|
{
|
||||||
id: expect.any(Number),
|
|
||||||
foreign: homeCom1.foreign,
|
foreign: homeCom1.foreign,
|
||||||
name: homeCom1.name,
|
name: homeCom1.name,
|
||||||
description: homeCom1.description,
|
description: homeCom1.description,
|
||||||
url: homeCom1.url,
|
url: homeCom1.url,
|
||||||
creationDate: homeCom1.creationDate?.toISOString(),
|
|
||||||
uuid: homeCom1.communityUuid,
|
uuid: homeCom1.communityUuid,
|
||||||
authenticatedAt: homeCom1.authenticatedAt?.toISOString(),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -602,81 +482,30 @@ describe('CommunityResolver', () => {
|
|||||||
|
|
||||||
describe('returns 2 filtered communities even with 3 existing entries', () => {
|
describe('returns 2 filtered communities even with 3 existing entries', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await cleanDB()
|
foreignCom1 = await createCommunity(true, false)
|
||||||
jest.clearAllMocks()
|
foreignCom2 = await createAuthenticatedForeignCommunity(100, false)
|
||||||
|
await Promise.all([
|
||||||
homeCom1 = DbCommunity.create()
|
DbCommunity.insert(foreignCom1),
|
||||||
homeCom1.foreign = false
|
DbCommunity.insert(foreignCom2)
|
||||||
homeCom1.url = 'http://localhost/api'
|
])
|
||||||
homeCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[0].public, 'hex')
|
|
||||||
homeCom1.privateKey = Buffer.from(ed25519KeyPairStaticHex[0].private, 'hex')
|
|
||||||
homeCom1.communityUuid = 'HomeCom-UUID'
|
|
||||||
homeCom1.authenticatedAt = new Date()
|
|
||||||
homeCom1.name = 'HomeCommunity-name'
|
|
||||||
homeCom1.description = 'HomeCommunity-description'
|
|
||||||
homeCom1.creationDate = new Date()
|
|
||||||
await DbCommunity.insert(homeCom1)
|
|
||||||
|
|
||||||
foreignCom1 = DbCommunity.create()
|
|
||||||
foreignCom1.foreign = true
|
|
||||||
foreignCom1.url = 'http://stage-2.gradido.net/api'
|
|
||||||
foreignCom1.publicKey = Buffer.from(ed25519KeyPairStaticHex[3].public, 'hex')
|
|
||||||
foreignCom1.privateKey = Buffer.from(ed25519KeyPairStaticHex[3].private, 'hex')
|
|
||||||
// foreignCom1.communityUuid = 'Stage2-Com-UUID'
|
|
||||||
// foreignCom1.authenticatedAt = new Date()
|
|
||||||
foreignCom1.name = 'Stage-2_Community-name'
|
|
||||||
foreignCom1.description = 'Stage-2_Community-description'
|
|
||||||
foreignCom1.creationDate = new Date()
|
|
||||||
await DbCommunity.insert(foreignCom1)
|
|
||||||
|
|
||||||
foreignCom2 = DbCommunity.create()
|
|
||||||
foreignCom2.foreign = true
|
|
||||||
foreignCom2.url = 'http://stage-3.gradido.net/api'
|
|
||||||
foreignCom2.publicKey = Buffer.from(ed25519KeyPairStaticHex[4].public, 'hex')
|
|
||||||
foreignCom2.privateKey = Buffer.from(ed25519KeyPairStaticHex[4].private, 'hex')
|
|
||||||
foreignCom2.communityUuid = 'Stage3-Com-UUID'
|
|
||||||
foreignCom2.authenticatedAt = new Date()
|
|
||||||
foreignCom2.name = 'Stage-3_Community-name'
|
|
||||||
foreignCom2.description = 'Stage-3_Community-description'
|
|
||||||
foreignCom2.creationDate = new Date()
|
|
||||||
await DbCommunity.insert(foreignCom2)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('returns 2 community entries', async () => {
|
it('returns 2 community entries', async () => {
|
||||||
await expect(query({ query: communitiesQuery })).resolves.toMatchObject({
|
await expect(query({ query: reachableCommunities })).resolves.toMatchObject({
|
||||||
data: {
|
data: {
|
||||||
communities: [
|
reachableCommunities: [
|
||||||
{
|
{
|
||||||
id: expect.any(Number),
|
|
||||||
foreign: homeCom1.foreign,
|
foreign: homeCom1.foreign,
|
||||||
name: homeCom1.name,
|
name: homeCom1.name,
|
||||||
description: homeCom1.description,
|
description: homeCom1.description,
|
||||||
url: homeCom1.url,
|
url: homeCom1.url,
|
||||||
creationDate: homeCom1.creationDate?.toISOString(),
|
|
||||||
uuid: homeCom1.communityUuid,
|
uuid: homeCom1.communityUuid,
|
||||||
authenticatedAt: homeCom1.authenticatedAt?.toISOString(),
|
}, {
|
||||||
},
|
|
||||||
/*
|
|
||||||
{
|
|
||||||
id: expect.any(Number),
|
|
||||||
foreign: foreignCom1.foreign,
|
|
||||||
name: foreignCom1.name,
|
|
||||||
description: foreignCom1.description,
|
|
||||||
url: foreignCom1.url,
|
|
||||||
creationDate: foreignCom1.creationDate?.toISOString(),
|
|
||||||
uuid: foreignCom1.communityUuid,
|
|
||||||
authenticatedAt: foreignCom1.authenticatedAt?.toISOString(),
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
id: expect.any(Number),
|
|
||||||
foreign: foreignCom2.foreign,
|
foreign: foreignCom2.foreign,
|
||||||
name: foreignCom2.name,
|
name: foreignCom2.name,
|
||||||
description: foreignCom2.description,
|
description: foreignCom2.description,
|
||||||
url: foreignCom2.url,
|
url: foreignCom2.url,
|
||||||
creationDate: foreignCom2.creationDate?.toISOString(),
|
|
||||||
uuid: foreignCom2.communityUuid,
|
uuid: foreignCom2.communityUuid,
|
||||||
authenticatedAt: foreignCom2.authenticatedAt?.toISOString(),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -686,51 +515,18 @@ describe('CommunityResolver', () => {
|
|||||||
|
|
||||||
describe('search community by uuid', () => {
|
describe('search community by uuid', () => {
|
||||||
let homeCom: DbCommunity | null
|
let homeCom: DbCommunity | null
|
||||||
beforeEach(async () => {
|
beforeAll(async () => {
|
||||||
await cleanDB()
|
await DbCommunity.clear()
|
||||||
jest.clearAllMocks()
|
|
||||||
const admin = await userFactory(testEnv, peterLustig)
|
|
||||||
// login as admin
|
|
||||||
await mutate({ mutation: login, variables: peterLoginData })
|
|
||||||
|
|
||||||
// HomeCommunity is still created in userFactory
|
homeCom = await createCommunity(false, false)
|
||||||
homeCom = await getCommunityByUuid(admin.communityUuid)
|
foreignCom1 = await createCommunity(true, false)
|
||||||
|
foreignCom2 = await createCommunity(true, false)
|
||||||
|
|
||||||
foreignCom1 = DbCommunity.create()
|
await Promise.all([
|
||||||
foreignCom1.foreign = true
|
DbCommunity.insert(homeCom),
|
||||||
foreignCom1.url = 'http://stage-2.gradido.net/api'
|
DbCommunity.insert(foreignCom1),
|
||||||
foreignCom1.publicKey = Buffer.from(
|
DbCommunity.insert(foreignCom2),
|
||||||
'8a1f9374b99c30d827b85dcd23f7e50328430d64ef65ef35bf375ea8eb9a2e1d',
|
])
|
||||||
'hex',
|
|
||||||
)
|
|
||||||
foreignCom1.privateKey = Buffer.from(
|
|
||||||
'f6c2a9d78e20a3c910f35b8ffcf824aa7b37f0d3d81bfc4c0e65e17a194b3a4a',
|
|
||||||
'hex',
|
|
||||||
)
|
|
||||||
// foreignCom1.communityUuid = 'Stage2-Com-UUID'
|
|
||||||
// foreignCom1.authenticatedAt = new Date()
|
|
||||||
foreignCom1.name = 'Stage-2_Community-name'
|
|
||||||
foreignCom1.description = 'Stage-2_Community-description'
|
|
||||||
foreignCom1.creationDate = new Date()
|
|
||||||
await DbCommunity.insert(foreignCom1)
|
|
||||||
|
|
||||||
foreignCom2 = DbCommunity.create()
|
|
||||||
foreignCom2.foreign = true
|
|
||||||
foreignCom2.url = 'http://stage-3.gradido.net/api'
|
|
||||||
foreignCom2.publicKey = Buffer.from(
|
|
||||||
'e047365a54082e8a7e9273da61b55c8134a2a0c836799ba12b78b9b0c52bc85f',
|
|
||||||
'hex',
|
|
||||||
)
|
|
||||||
foreignCom2.privateKey = Buffer.from(
|
|
||||||
'e047365a54082e8a7e9273da61b55c8134a2a0c836799ba12b78b9b0c52bc85f',
|
|
||||||
'hex',
|
|
||||||
)
|
|
||||||
foreignCom2.communityUuid = uuidv4()
|
|
||||||
foreignCom2.authenticatedAt = new Date()
|
|
||||||
foreignCom2.name = 'Stage-3_Community-name'
|
|
||||||
foreignCom2.description = 'Stage-3_Community-description'
|
|
||||||
foreignCom2.creationDate = new Date()
|
|
||||||
await DbCommunity.insert(foreignCom2)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('finds the home-community by uuid', async () => {
|
it('finds the home-community by uuid', async () => {
|
||||||
@ -749,7 +545,6 @@ describe('CommunityResolver', () => {
|
|||||||
url: homeCom?.url,
|
url: homeCom?.url,
|
||||||
creationDate: homeCom?.creationDate?.toISOString(),
|
creationDate: homeCom?.creationDate?.toISOString(),
|
||||||
uuid: homeCom?.communityUuid,
|
uuid: homeCom?.communityUuid,
|
||||||
authenticatedAt: homeCom?.authenticatedAt,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -769,76 +564,100 @@ describe('CommunityResolver', () => {
|
|||||||
description: homeCom?.description,
|
description: homeCom?.description,
|
||||||
url: homeCom?.url,
|
url: homeCom?.url,
|
||||||
creationDate: homeCom?.creationDate?.toISOString(),
|
creationDate: homeCom?.creationDate?.toISOString(),
|
||||||
uuid: homeCom?.communityUuid,
|
uuid: homeCom?.communityUuid
|
||||||
authenticatedAt: homeCom?.authenticatedAt,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
})
|
||||||
it('updates the home-community gmsApiKey', async () => {
|
})
|
||||||
await expect(
|
|
||||||
mutate({
|
describe('update community', () => {
|
||||||
mutation: updateHomeCommunityQuery,
|
let homeCom: DbCommunity
|
||||||
variables: { uuid: homeCom?.communityUuid, gmsApiKey: 'gmsApiKey' },
|
let foreignCom1: DbCommunity
|
||||||
}),
|
let foreignCom2: DbCommunity
|
||||||
).resolves.toMatchObject({
|
|
||||||
data: {
|
beforeAll(async () => {
|
||||||
updateHomeCommunity: {
|
await DbCommunity.clear()
|
||||||
id: expect.any(Number),
|
|
||||||
foreign: homeCom?.foreign,
|
// create admin and login as admin
|
||||||
name: homeCom?.name,
|
await userFactory(testEnv, peterLustig)
|
||||||
description: homeCom?.description,
|
homeCom = (await getHomeCommunity())!
|
||||||
url: homeCom?.url,
|
foreignCom1 = await createCommunity(true, false)
|
||||||
creationDate: homeCom?.creationDate?.toISOString(),
|
foreignCom2 = await createCommunity(true, false)
|
||||||
uuid: homeCom?.communityUuid,
|
|
||||||
authenticatedAt: homeCom?.authenticatedAt,
|
await Promise.all([
|
||||||
gmsApiKey: 'gmsApiKey',
|
DbCommunity.insert(foreignCom1),
|
||||||
},
|
DbCommunity.insert(foreignCom2),
|
||||||
},
|
mutate({ mutation: login, variables: peterLoginData })
|
||||||
})
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('throws error on updating a foreign-community', async () => {
|
afterAll(async () => {
|
||||||
expect(
|
await cleanDB()
|
||||||
await mutate({
|
})
|
||||||
mutation: updateHomeCommunityQuery,
|
|
||||||
variables: { uuid: foreignCom2.communityUuid, gmsApiKey: 'gmsApiKey' },
|
it('updates the home-community gmsApiKey', async () => {
|
||||||
}),
|
await expect(
|
||||||
).toEqual(
|
mutate({
|
||||||
expect.objectContaining({
|
mutation: updateHomeCommunityQuery,
|
||||||
errors: [new GraphQLError('Error: Only the HomeCommunity could be modified!')],
|
variables: { uuid: homeCom?.communityUuid, gmsApiKey: 'gmsApiKey' },
|
||||||
}),
|
}),
|
||||||
)
|
).resolves.toMatchObject({
|
||||||
})
|
data: {
|
||||||
|
updateHomeCommunity: {
|
||||||
it('throws error on updating a community without uuid', async () => {
|
foreign: homeCom?.foreign,
|
||||||
expect(
|
name: homeCom?.name,
|
||||||
await mutate({
|
description: homeCom?.description,
|
||||||
mutation: updateHomeCommunityQuery,
|
url: homeCom?.url,
|
||||||
variables: { uuid: null, gmsApiKey: 'gmsApiKey' },
|
creationDate: homeCom?.creationDate?.toISOString(),
|
||||||
}),
|
uuid: homeCom?.communityUuid,
|
||||||
).toEqual(
|
authenticatedAt: homeCom?.authenticatedAt,
|
||||||
expect.objectContaining({
|
gmsApiKey: 'gmsApiKey',
|
||||||
errors: [
|
},
|
||||||
new GraphQLError(`Variable "$uuid" of non-null type "String!" must not be null.`),
|
},
|
||||||
],
|
})
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
})
|
it('throws error on updating a foreign-community', async () => {
|
||||||
|
expect(
|
||||||
it('throws error on updating a community with not existing uuid', async () => {
|
await mutate({
|
||||||
expect(
|
mutation: updateHomeCommunityQuery,
|
||||||
await mutate({
|
variables: { uuid: foreignCom2.communityUuid, gmsApiKey: 'gmsApiKey' },
|
||||||
mutation: updateHomeCommunityQuery,
|
}),
|
||||||
variables: { uuid: uuidv4(), gmsApiKey: 'gmsApiKey' },
|
).toEqual(
|
||||||
}),
|
expect.objectContaining({
|
||||||
).toEqual(
|
errors: [new GraphQLError('Error: Only the HomeCommunity could be modified!')],
|
||||||
expect.objectContaining({
|
}),
|
||||||
errors: [new GraphQLError('HomeCommunity with uuid not found: ')],
|
)
|
||||||
}),
|
})
|
||||||
)
|
|
||||||
})
|
it('throws error on updating a community without uuid', async () => {
|
||||||
|
expect(
|
||||||
|
await mutate({
|
||||||
|
mutation: updateHomeCommunityQuery,
|
||||||
|
variables: { uuid: null, gmsApiKey: 'gmsApiKey' },
|
||||||
|
}),
|
||||||
|
).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [
|
||||||
|
new GraphQLError(`Variable "$uuid" of non-null type "String!" must not be null.`),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('throws error on updating a community with not existing uuid', async () => {
|
||||||
|
expect(
|
||||||
|
await mutate({
|
||||||
|
mutation: updateHomeCommunityQuery,
|
||||||
|
variables: { uuid: uuidv4(), gmsApiKey: 'gmsApiKey' },
|
||||||
|
}),
|
||||||
|
).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
errors: [new GraphQLError('HomeCommunity with uuid not found: ')],
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
import { Community as DbCommunity, FederatedCommunity as DbFederatedCommunity, getHomeCommunity } from 'database'
|
import {
|
||||||
|
Community as DbCommunity,
|
||||||
|
getReachableCommunities,
|
||||||
|
getCommunityWithFederatedCommunityByIdentifier,
|
||||||
|
getHomeCommunity
|
||||||
|
} from 'database'
|
||||||
import { Arg, Args, Authorized, Mutation, Query, Resolver } from 'type-graphql'
|
import { Arg, Args, Authorized, Mutation, Query, Resolver } from 'type-graphql'
|
||||||
import { IsNull, Not } from 'typeorm'
|
|
||||||
|
|
||||||
import { Paginated } from '@arg/Paginated'
|
import { Paginated } from '@arg/Paginated'
|
||||||
import { EditCommunityInput } from '@input/EditCommunityInput'
|
import { EditCommunityInput } from '@input/EditCommunityInput'
|
||||||
import { AdminCommunityView } from '@model/AdminCommunityView'
|
import { AdminCommunityView } from '@model/AdminCommunityView'
|
||||||
import { Community } from '@model/Community'
|
import { Community } from '@model/Community'
|
||||||
import { FederatedCommunity } from '@model/FederatedCommunity'
|
|
||||||
|
|
||||||
import { RIGHTS } from '@/auth/RIGHTS'
|
import { RIGHTS } from '@/auth/RIGHTS'
|
||||||
import { LogError } from '@/server/LogError'
|
import { LogError } from '@/server/LogError'
|
||||||
@ -18,24 +21,16 @@ import {
|
|||||||
getCommunityByUuid,
|
getCommunityByUuid,
|
||||||
} from './util/communities'
|
} from './util/communities'
|
||||||
|
|
||||||
|
import { LOG4JS_BASE_CATEGORY_NAME } from '@/config/const'
|
||||||
|
import { getLogger } from 'log4js'
|
||||||
|
import { communityIsReachable, CommunityIsReachableResult } from '../logic/communityIsReachable'
|
||||||
|
import { CONFIG } from '@/config'
|
||||||
|
|
||||||
|
const logger = getLogger(`${LOG4JS_BASE_CATEGORY_NAME}.graphql.resolver.CommunityResolver`)
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class CommunityResolver {
|
export class CommunityResolver {
|
||||||
@Authorized([RIGHTS.COMMUNITIES])
|
@Authorized([RIGHTS.COMMUNITY_WITH_API_KEYS])
|
||||||
@Query(() => [FederatedCommunity])
|
|
||||||
async getCommunities(): Promise<FederatedCommunity[]> {
|
|
||||||
const dbFederatedCommunities: DbFederatedCommunity[] = await DbFederatedCommunity.find({
|
|
||||||
order: {
|
|
||||||
foreign: 'ASC',
|
|
||||||
createdAt: 'DESC',
|
|
||||||
lastAnnouncedAt: 'DESC',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return dbFederatedCommunities.map(
|
|
||||||
(dbCom: DbFederatedCommunity) => new FederatedCommunity(dbCom),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Authorized([RIGHTS.COMMUNITIES])
|
|
||||||
@Query(() => [AdminCommunityView])
|
@Query(() => [AdminCommunityView])
|
||||||
async allCommunities(@Args() paginated: Paginated): Promise<AdminCommunityView[]> {
|
async allCommunities(@Args() paginated: Paginated): Promise<AdminCommunityView[]> {
|
||||||
// communityUUID could be oneTimePassCode (uint32 number)
|
// communityUUID could be oneTimePassCode (uint32 number)
|
||||||
@ -44,17 +39,17 @@ export class CommunityResolver {
|
|||||||
|
|
||||||
@Authorized([RIGHTS.COMMUNITIES])
|
@Authorized([RIGHTS.COMMUNITIES])
|
||||||
@Query(() => [Community])
|
@Query(() => [Community])
|
||||||
async communities(): Promise<Community[]> {
|
async reachableCommunities(): Promise<Community[]> {
|
||||||
const dbCommunities: DbCommunity[] = await DbCommunity.find({
|
const dbCommunities: DbCommunity[] = await getReachableCommunities(
|
||||||
where: { communityUuid: Not(IsNull()) }, //, authenticatedAt: Not(IsNull()) },
|
CONFIG.FEDERATION_VALIDATE_COMMUNITY_TIMER * 2, {
|
||||||
order: {
|
// order by
|
||||||
name: 'ASC',
|
foreign: 'ASC', // home community first
|
||||||
},
|
name: 'ASC', // sort foreign communities by name
|
||||||
})
|
})
|
||||||
return dbCommunities.map((dbCom: DbCommunity) => new Community(dbCom))
|
return dbCommunities.map((dbCom: DbCommunity) => new Community(dbCom))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Authorized([RIGHTS.COMMUNITY_BY_IDENTIFIER])
|
@Authorized([RIGHTS.COMMUNITIES])
|
||||||
@Query(() => Community)
|
@Query(() => Community)
|
||||||
async communityByIdentifier(
|
async communityByIdentifier(
|
||||||
@Arg('communityIdentifier') communityIdentifier: string,
|
@Arg('communityIdentifier') communityIdentifier: string,
|
||||||
@ -67,7 +62,7 @@ export class CommunityResolver {
|
|||||||
return new Community(community)
|
return new Community(community)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Authorized([RIGHTS.HOME_COMMUNITY])
|
@Authorized([RIGHTS.COMMUNITIES])
|
||||||
@Query(() => Community)
|
@Query(() => Community)
|
||||||
async homeCommunity(): Promise<Community> {
|
async homeCommunity(): Promise<Community> {
|
||||||
const community = await getHomeCommunity()
|
const community = await getHomeCommunity()
|
||||||
@ -78,10 +73,10 @@ export class CommunityResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Authorized([RIGHTS.COMMUNITY_UPDATE])
|
@Authorized([RIGHTS.COMMUNITY_UPDATE])
|
||||||
@Mutation(() => Community)
|
@Mutation(() => AdminCommunityView)
|
||||||
async updateHomeCommunity(
|
async updateHomeCommunity(
|
||||||
@Args() { uuid, gmsApiKey, location, hieroTopicId }: EditCommunityInput,
|
@Args() { uuid, gmsApiKey, location, hieroTopicId }: EditCommunityInput,
|
||||||
): Promise<Community> {
|
): Promise<AdminCommunityView> {
|
||||||
const homeCom = await getCommunityByUuid(uuid)
|
const homeCom = await getCommunityByUuid(uuid)
|
||||||
if (!homeCom) {
|
if (!homeCom) {
|
||||||
throw new LogError('HomeCommunity with uuid not found: ', uuid)
|
throw new LogError('HomeCommunity with uuid not found: ', uuid)
|
||||||
@ -89,18 +84,24 @@ export class CommunityResolver {
|
|||||||
if (homeCom.foreign) {
|
if (homeCom.foreign) {
|
||||||
throw new LogError('Error: Only the HomeCommunity could be modified!')
|
throw new LogError('Error: Only the HomeCommunity could be modified!')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
homeCom.gmsApiKey !== gmsApiKey ||
|
homeCom.gmsApiKey !== gmsApiKey ||
|
||||||
homeCom.location !== location ||
|
homeCom.location !== location ||
|
||||||
homeCom.hieroTopicId !== hieroTopicId
|
homeCom.hieroTopicId !== hieroTopicId
|
||||||
) {
|
) {
|
||||||
|
// TODO: think about this, it is really expected to delete gmsApiKey if no new one is given?
|
||||||
homeCom.gmsApiKey = gmsApiKey ?? null
|
homeCom.gmsApiKey = gmsApiKey ?? null
|
||||||
if (location) {
|
if (location) {
|
||||||
homeCom.location = Location2Point(location)
|
homeCom.location = Location2Point(location)
|
||||||
}
|
}
|
||||||
homeCom.hieroTopicId = hieroTopicId ?? null
|
// update only with new value, don't overwrite existing value with null or undefined!
|
||||||
|
if (hieroTopicId) {
|
||||||
|
homeCom.hieroTopicId = hieroTopicId
|
||||||
|
}
|
||||||
await DbCommunity.save(homeCom)
|
await DbCommunity.save(homeCom)
|
||||||
}
|
}
|
||||||
return new Community(homeCom)
|
|
||||||
|
return new AdminCommunityView(homeCom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -48,7 +48,6 @@ import { randombytes_random } from 'sodium-native'
|
|||||||
import { executeTransaction } from './TransactionResolver'
|
import { executeTransaction } from './TransactionResolver'
|
||||||
import {
|
import {
|
||||||
getAuthenticatedCommunities,
|
getAuthenticatedCommunities,
|
||||||
getCommunityByIdentifier,
|
|
||||||
getCommunityByPublicKey,
|
getCommunityByPublicKey,
|
||||||
getCommunityByUuid,
|
getCommunityByUuid,
|
||||||
} from './util/communities'
|
} from './util/communities'
|
||||||
|
|||||||
@ -439,9 +439,7 @@ export class TransactionResolver {
|
|||||||
logger.debug(
|
logger.debug(
|
||||||
`sendCoins(recipientCommunityIdentifier=${recipientCommunityIdentifier}, recipientIdentifier=${recipientIdentifier}, amount=${amount}, memo=${memo})`,
|
`sendCoins(recipientCommunityIdentifier=${recipientCommunityIdentifier}, recipientIdentifier=${recipientIdentifier}, amount=${amount}, memo=${memo})`,
|
||||||
)
|
)
|
||||||
const homeCom = await DbCommunity.findOneOrFail({ where: { foreign: false } })
|
|
||||||
const senderUser = getUser(context)
|
const senderUser = getUser(context)
|
||||||
|
|
||||||
if (!recipientCommunityIdentifier || (await isHomeCommunity(recipientCommunityIdentifier))) {
|
if (!recipientCommunityIdentifier || (await isHomeCommunity(recipientCommunityIdentifier))) {
|
||||||
// processing sendCoins within sender and recipient are both in home community
|
// processing sendCoins within sender and recipient are both in home community
|
||||||
const recipientUser = await findUserByIdentifier(
|
const recipientUser = await findUserByIdentifier(
|
||||||
@ -449,7 +447,7 @@ export class TransactionResolver {
|
|||||||
recipientCommunityIdentifier,
|
recipientCommunityIdentifier,
|
||||||
)
|
)
|
||||||
if (!recipientUser) {
|
if (!recipientUser) {
|
||||||
throw new LogError('The recipient user was not found', recipientUser)
|
throw new LogError('The recipient user was not found', { recipientIdentifier, recipientCommunityIdentifier })
|
||||||
}
|
}
|
||||||
logger.addContext('to', recipientUser?.id)
|
logger.addContext('to', recipientUser?.id)
|
||||||
if (recipientUser.foreign) {
|
if (recipientUser.foreign) {
|
||||||
|
|||||||
@ -1151,6 +1151,12 @@ export class UserResolver {
|
|||||||
@Args()
|
@Args()
|
||||||
{ identifier, communityIdentifier }: UserArgs,
|
{ identifier, communityIdentifier }: UserArgs,
|
||||||
): Promise<User> {
|
): Promise<User> {
|
||||||
|
// check if identifier contain community and user identifier
|
||||||
|
if (identifier.includes('/')) {
|
||||||
|
const parts = identifier.split('/')
|
||||||
|
communityIdentifier = parts[0]
|
||||||
|
identifier = parts[1]
|
||||||
|
}
|
||||||
const foundDbUser = await findUserByIdentifier(identifier, communityIdentifier)
|
const foundDbUser = await findUserByIdentifier(identifier, communityIdentifier)
|
||||||
if (!foundDbUser) {
|
if (!foundDbUser) {
|
||||||
createLogger().debug('User not found', identifier, communityIdentifier)
|
createLogger().debug('User not found', identifier, communityIdentifier)
|
||||||
|
|||||||
@ -375,7 +375,6 @@ export const logout = gql`
|
|||||||
export const updateHomeCommunityQuery = gql`
|
export const updateHomeCommunityQuery = gql`
|
||||||
mutation ($uuid: String!, $gmsApiKey: String!) {
|
mutation ($uuid: String!, $gmsApiKey: String!) {
|
||||||
updateHomeCommunity(uuid: $uuid, gmsApiKey: $gmsApiKey) {
|
updateHomeCommunity(uuid: $uuid, gmsApiKey: $gmsApiKey) {
|
||||||
id
|
|
||||||
foreign
|
foreign
|
||||||
name
|
name
|
||||||
description
|
description
|
||||||
|
|||||||
@ -135,18 +135,14 @@ export const listGDTEntriesQuery = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const communitiesQuery = gql`
|
export const reachableCommunities = gql`
|
||||||
query {
|
query {
|
||||||
communities {
|
reachableCommunities {
|
||||||
id
|
|
||||||
foreign
|
foreign
|
||||||
|
uuid
|
||||||
name
|
name
|
||||||
description
|
description
|
||||||
url
|
url
|
||||||
creationDate
|
|
||||||
uuid
|
|
||||||
authenticatedAt
|
|
||||||
gmsApiKey
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -162,7 +158,6 @@ export const getCommunityByIdentifierQuery = gql`
|
|||||||
creationDate
|
creationDate
|
||||||
uuid
|
uuid
|
||||||
authenticatedAt
|
authenticatedAt
|
||||||
gmsApiKey
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -178,24 +173,6 @@ export const getHomeCommunityQuery = gql`
|
|||||||
creationDate
|
creationDate
|
||||||
uuid
|
uuid
|
||||||
authenticatedAt
|
authenticatedAt
|
||||||
gmsApiKey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export const getCommunities = gql`
|
|
||||||
query {
|
|
||||||
getCommunities {
|
|
||||||
id
|
|
||||||
foreign
|
|
||||||
publicKey
|
|
||||||
endPoint
|
|
||||||
apiVersion
|
|
||||||
lastAnnouncedAt
|
|
||||||
verifiedAt
|
|
||||||
lastErrorAt
|
|
||||||
createdAt
|
|
||||||
updatedAt
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
@ -268,7 +245,7 @@ export const listContributions = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const listAllContributions = `
|
export const listAllContributions = gql`
|
||||||
query ($pagination: Paginated!) {
|
query ($pagination: Paginated!) {
|
||||||
listAllContributions(pagination: $pagination) {
|
listAllContributions(pagination: $pagination) {
|
||||||
contributionCount
|
contributionCount
|
||||||
|
|||||||
@ -39,11 +39,13 @@ export const testEnvironment = async (testLogger = getLogger('apollo'), testI18n
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const resetEntity = async (entity: any) => {
|
export const resetEntity = async (entity: any) => {
|
||||||
const items = await entity.find({ withDeleted: true })
|
// delete data and reset autoincrement!
|
||||||
|
await entity.clear()
|
||||||
|
/*const items = await entity.find({ withDeleted: true })
|
||||||
if (items.length > 0) {
|
if (items.length > 0) {
|
||||||
const ids = items.map((e: any) => e.id)
|
const ids = items.map((e: any) => e.id)
|
||||||
await entity.delete(ids)
|
await entity.delete(ids)
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
export const resetToken = () => {
|
export const resetToken = () => {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Community as DbCommunity } from '..'
|
import { Community as DbCommunity } from '..'
|
||||||
import { AppDatabase } from '../AppDatabase'
|
import { AppDatabase } from '../AppDatabase'
|
||||||
import { getHomeCommunity } from './communities'
|
import { getHomeCommunity, getReachableCommunities } from './communities'
|
||||||
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
|
import { describe, expect, it, beforeEach, beforeAll, afterAll } from 'vitest'
|
||||||
import { createCommunity } from '../seeds/homeCommunity'
|
import { createCommunity, createAuthenticatedForeignCommunity } from '../seeds/community'
|
||||||
|
|
||||||
const db = AppDatabase.getInstance()
|
const db = AppDatabase.getInstance()
|
||||||
|
|
||||||
@ -14,7 +14,8 @@ afterAll(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('community.queries', () => {
|
describe('community.queries', () => {
|
||||||
beforeAll(async () => {
|
// clean db for every test case
|
||||||
|
beforeEach(async () => {
|
||||||
await DbCommunity.clear()
|
await DbCommunity.clear()
|
||||||
})
|
})
|
||||||
describe('getHomeCommunity', () => {
|
describe('getHomeCommunity', () => {
|
||||||
@ -37,4 +38,28 @@ describe('community.queries', () => {
|
|||||||
expect(community?.privateKey).toStrictEqual(homeCom.privateKey)
|
expect(community?.privateKey).toStrictEqual(homeCom.privateKey)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
describe('getReachableCommunities', () => {
|
||||||
|
it('home community counts also to reachable communities', async () => {
|
||||||
|
await createCommunity(false)
|
||||||
|
expect(await getReachableCommunities(1000)).toHaveLength(1)
|
||||||
|
})
|
||||||
|
it('foreign communities authenticated within chosen range', async () => {
|
||||||
|
await createAuthenticatedForeignCommunity(400)
|
||||||
|
await createAuthenticatedForeignCommunity(500)
|
||||||
|
await createAuthenticatedForeignCommunity(1200)
|
||||||
|
|
||||||
|
const community = await getReachableCommunities(1000)
|
||||||
|
expect(community).toHaveLength(2)
|
||||||
|
})
|
||||||
|
it('foreign and home community', async () => {
|
||||||
|
await createCommunity(false)
|
||||||
|
await createAuthenticatedForeignCommunity(400)
|
||||||
|
await createAuthenticatedForeignCommunity(1200)
|
||||||
|
expect(await getReachableCommunities(1000)).toHaveLength(2)
|
||||||
|
})
|
||||||
|
it('not authenticated foreign community', async () => {
|
||||||
|
await createCommunity(true)
|
||||||
|
expect(await getReachableCommunities(1000)).toHaveLength(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
@ -1,10 +1,14 @@
|
|||||||
|
import { FindOptionsOrder, FindOptionsWhere, IsNull, MoreThanOrEqual, Not } from 'typeorm'
|
||||||
import { Community as DbCommunity } from '../entity'
|
import { Community as DbCommunity } from '../entity'
|
||||||
|
import { urlSchema, uuidv4Schema } from 'shared'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the home community, i.e., a community that is not foreign.
|
* Retrieves the home community, i.e., a community that is not foreign.
|
||||||
* @returns A promise that resolves to the home community, or null if no home community was found
|
* @returns A promise that resolves to the home community, or null if no home community was found
|
||||||
*/
|
*/
|
||||||
export async function getHomeCommunity(): Promise<DbCommunity | null> {
|
export async function getHomeCommunity(): Promise<DbCommunity | null> {
|
||||||
|
// TODO: Put in Cache, it is needed nearly always
|
||||||
|
// TODO: return only DbCommunity or throw to reduce unnecessary checks, because there should be always a home community
|
||||||
return await DbCommunity.findOne({
|
return await DbCommunity.findOne({
|
||||||
where: { foreign: false },
|
where: { foreign: false },
|
||||||
})
|
})
|
||||||
@ -15,3 +19,40 @@ export async function getCommunityByUuid(communityUuid: string): Promise<DbCommu
|
|||||||
where: [{ communityUuid }],
|
where: [{ communityUuid }],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function findWithCommunityIdentifier(communityIdentifier: string): FindOptionsWhere<DbCommunity> {
|
||||||
|
const where: FindOptionsWhere<DbCommunity> = {}
|
||||||
|
// pre filter identifier type to reduce db query complexity
|
||||||
|
if (urlSchema.safeParse(communityIdentifier).success) {
|
||||||
|
where.url = communityIdentifier
|
||||||
|
} else if (uuidv4Schema.safeParse(communityIdentifier).success) {
|
||||||
|
where.communityUuid = communityIdentifier
|
||||||
|
} else {
|
||||||
|
where.name = communityIdentifier
|
||||||
|
}
|
||||||
|
return where
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getCommunityWithFederatedCommunityByIdentifier(
|
||||||
|
communityIdentifier: string,
|
||||||
|
): Promise<DbCommunity | null> {
|
||||||
|
return await DbCommunity.findOne({
|
||||||
|
where: { ...findWithCommunityIdentifier(communityIdentifier) },
|
||||||
|
relations: ['federatedCommunities'],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns all reachable communities
|
||||||
|
// home community and all foreign communities which have been authenticated within the last authenticationTimeoutMs
|
||||||
|
export async function getReachableCommunities(
|
||||||
|
authenticationTimeoutMs: number,
|
||||||
|
order?: FindOptionsOrder<DbCommunity>
|
||||||
|
): Promise<DbCommunity[]> {
|
||||||
|
return await DbCommunity.find({
|
||||||
|
where: [
|
||||||
|
{ communityUuid: Not(IsNull()), authenticatedAt: MoreThanOrEqual(new Date(Date.now() - authenticationTimeoutMs)) },
|
||||||
|
{ foreign: false },
|
||||||
|
],
|
||||||
|
order,
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -14,7 +14,7 @@ import { peterLustig } from '../seeds/users/peter-lustig'
|
|||||||
import { bobBaumeister } from '../seeds/users/bob-baumeister'
|
import { bobBaumeister } from '../seeds/users/bob-baumeister'
|
||||||
import { garrickOllivander } from '../seeds/users/garrick-ollivander'
|
import { garrickOllivander } from '../seeds/users/garrick-ollivander'
|
||||||
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
|
import { describe, expect, it, beforeAll, afterAll } from 'vitest'
|
||||||
import { createCommunity } from '../seeds/homeCommunity'
|
import { createCommunity } from '../seeds/community'
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
import Decimal from 'decimal.js-light'
|
import Decimal from 'decimal.js-light'
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { aliasExists, findUserByIdentifier } from './user'
|
|||||||
import { userFactory } from '../seeds/factory/user'
|
import { userFactory } from '../seeds/factory/user'
|
||||||
import { bibiBloxberg } from '../seeds/users/bibi-bloxberg'
|
import { bibiBloxberg } from '../seeds/users/bibi-bloxberg'
|
||||||
import { describe, expect, it, beforeAll, afterAll, beforeEach, } from 'vitest'
|
import { describe, expect, it, beforeAll, afterAll, beforeEach, } from 'vitest'
|
||||||
import { createCommunity } from '../seeds/homeCommunity'
|
import { createCommunity } from '../seeds/community'
|
||||||
import { peterLustig } from '../seeds/users/peter-lustig'
|
import { peterLustig } from '../seeds/users/peter-lustig'
|
||||||
import { bobBaumeister } from '../seeds/users/bob-baumeister'
|
import { bobBaumeister } from '../seeds/users/bob-baumeister'
|
||||||
import { getLogger, printLogs, clearLogs } from '../../../config-schema/test/testSetup.vitest'
|
import { getLogger, printLogs, clearLogs } from '../../../config-schema/test/testSetup.vitest'
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
import { Raw } from 'typeorm'
|
import { Raw } from 'typeorm'
|
||||||
import { Community, User as DbUser, UserContact as DbUserContact } from '../entity'
|
import { User as DbUser, UserContact as DbUserContact } from '../entity'
|
||||||
import { FindOptionsWhere } from 'typeorm'
|
import { aliasSchema, emailSchema, uuidv4Schema } from 'shared'
|
||||||
import { aliasSchema, emailSchema, uuidv4Schema, urlSchema } from 'shared'
|
|
||||||
import { getLogger } from 'log4js'
|
import { getLogger } from 'log4js'
|
||||||
import { LOG4JS_QUERIES_CATEGORY_NAME } from './index'
|
import { findWithCommunityIdentifier, LOG4JS_QUERIES_CATEGORY_NAME } from './index'
|
||||||
|
|
||||||
export async function aliasExists(alias: string): Promise<boolean> {
|
export async function aliasExists(alias: string): Promise<boolean> {
|
||||||
const user = await DbUser.findOne({
|
const user = await DbUser.findOne({
|
||||||
@ -22,11 +21,9 @@ export const findUserByIdentifier = async (
|
|||||||
identifier: string,
|
identifier: string,
|
||||||
communityIdentifier?: string,
|
communityIdentifier?: string,
|
||||||
): Promise<DbUser | null> => {
|
): Promise<DbUser | null> => {
|
||||||
const communityWhere: FindOptionsWhere<Community> = urlSchema.safeParse(communityIdentifier).success
|
const communityWhere = communityIdentifier
|
||||||
? { url: communityIdentifier }
|
? findWithCommunityIdentifier(communityIdentifier)
|
||||||
: uuidv4Schema.safeParse(communityIdentifier).success
|
: undefined
|
||||||
? { communityUuid: communityIdentifier }
|
|
||||||
: { name: communityIdentifier }
|
|
||||||
|
|
||||||
if (uuidv4Schema.safeParse(identifier).success) {
|
if (uuidv4Schema.safeParse(identifier).success) {
|
||||||
return DbUser.findOne({
|
return DbUser.findOne({
|
||||||
|
|||||||
34
database/src/seeds/community.ts
Normal file
34
database/src/seeds/community.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { Community } from '../entity'
|
||||||
|
import { randomBytes } from 'node:crypto'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
|
export async function createCommunity(foreign: boolean, save: boolean = true): Promise<Community> {
|
||||||
|
const community = new Community()
|
||||||
|
community.publicKey = randomBytes(32)
|
||||||
|
community.communityUuid = uuidv4()
|
||||||
|
community.name = 'HomeCommunity-name'
|
||||||
|
community.creationDate = new Date()
|
||||||
|
|
||||||
|
if(foreign) {
|
||||||
|
community.foreign = true
|
||||||
|
community.name = 'ForeignCommunity-name'
|
||||||
|
community.description = 'ForeignCommunity-description'
|
||||||
|
community.url = `http://foreign-${Math.random()}/api`
|
||||||
|
} else {
|
||||||
|
community.foreign = false
|
||||||
|
community.privateKey = randomBytes(64)
|
||||||
|
community.name = 'HomeCommunity-name'
|
||||||
|
community.description = 'HomeCommunity-description'
|
||||||
|
community.url = 'http://localhost/api'
|
||||||
|
}
|
||||||
|
return save ? await community.save() : community
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createAuthenticatedForeignCommunity(
|
||||||
|
authenticatedBeforeMs: number,
|
||||||
|
save: boolean = true
|
||||||
|
): Promise<Community> {
|
||||||
|
const foreignCom = await createCommunity(true, false)
|
||||||
|
foreignCom.authenticatedAt = new Date(Date.now() - authenticatedBeforeMs)
|
||||||
|
return save ? await foreignCom.save() : foreignCom
|
||||||
|
}
|
||||||
@ -1,26 +0,0 @@
|
|||||||
import { Community } from '../entity'
|
|
||||||
import { randomBytes } from 'node:crypto'
|
|
||||||
import { v4 as uuidv4 } from 'uuid'
|
|
||||||
|
|
||||||
export async function createCommunity(foreign: boolean): Promise<Community> {
|
|
||||||
const homeCom = new Community()
|
|
||||||
homeCom.publicKey = randomBytes(32)
|
|
||||||
homeCom.communityUuid = uuidv4()
|
|
||||||
homeCom.authenticatedAt = new Date()
|
|
||||||
homeCom.name = 'HomeCommunity-name'
|
|
||||||
homeCom.creationDate = new Date()
|
|
||||||
|
|
||||||
if(foreign) {
|
|
||||||
homeCom.foreign = true
|
|
||||||
homeCom.name = 'ForeignCommunity-name'
|
|
||||||
homeCom.description = 'ForeignCommunity-description'
|
|
||||||
homeCom.url = 'http://foreign/api'
|
|
||||||
} else {
|
|
||||||
homeCom.foreign = false
|
|
||||||
homeCom.privateKey = randomBytes(64)
|
|
||||||
homeCom.name = 'HomeCommunity-name'
|
|
||||||
homeCom.description = 'HomeCommunity-description'
|
|
||||||
homeCom.url = 'http://localhost/api'
|
|
||||||
}
|
|
||||||
return await homeCom.save()
|
|
||||||
}
|
|
||||||
@ -25,7 +25,7 @@
|
|||||||
import { ref, computed, onMounted } from 'vue'
|
import { ref, computed, onMounted } from 'vue'
|
||||||
import { useQuery } from '@vue/apollo-composable'
|
import { useQuery } from '@vue/apollo-composable'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { selectCommunities } from '@/graphql/queries'
|
import { reachableCommunities } from '@/graphql/communities.graphql'
|
||||||
import { useAppToast } from '@/composables/useToast'
|
import { useAppToast } from '@/composables/useToast'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -35,7 +35,7 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue', 'communitiesLoaded'])
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const { toastError } = useAppToast()
|
const { toastError } = useAppToast()
|
||||||
@ -43,16 +43,17 @@ const { toastError } = useAppToast()
|
|||||||
const communities = ref([])
|
const communities = ref([])
|
||||||
const validCommunityIdentifier = ref(false)
|
const validCommunityIdentifier = ref(false)
|
||||||
|
|
||||||
const { onResult } = useQuery(selectCommunities)
|
const { onResult } = useQuery(reachableCommunities)
|
||||||
|
|
||||||
onResult(({ data }) => {
|
onResult(({ data }) => {
|
||||||
// console.log('CommunitySwitch.onResult...data=', data)
|
// console.log('CommunitySwitch.onResult...data=', data)
|
||||||
if (data) {
|
if (data) {
|
||||||
communities.value = data.communities
|
communities.value = data.reachableCommunities
|
||||||
setDefaultCommunity()
|
setDefaultCommunity()
|
||||||
if (data.communities.length === 1) {
|
if (data.reachableCommunities.length === 1) {
|
||||||
validCommunityIdentifier.value = true
|
validCommunityIdentifier.value = true
|
||||||
}
|
}
|
||||||
|
emit('communitiesLoaded', data.reachableCommunities)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@ vi.mock('vue-router', () => ({
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
const mockUseQuery = vi.fn()
|
const mockUseQuery = vi.fn()
|
||||||
|
const mockUseLazyQuery = vi.fn()
|
||||||
vi.mock('@vue/apollo-composable', () => ({
|
vi.mock('@vue/apollo-composable', () => ({
|
||||||
useQuery: (...args) => {
|
useQuery: (...args) => {
|
||||||
mockUseQuery(...args)
|
mockUseQuery(...args)
|
||||||
@ -35,6 +36,12 @@ vi.mock('@vue/apollo-composable', () => ({
|
|||||||
error: ref(null),
|
error: ref(null),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
useLazyQuery: (...args) => {
|
||||||
|
mockUseLazyQuery(...args)
|
||||||
|
return {
|
||||||
|
refetch: vi.fn(() => true),
|
||||||
|
}
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('@/composables/useToast', () => ({
|
vi.mock('@/composables/useToast', () => ({
|
||||||
|
|||||||
@ -49,6 +49,7 @@
|
|||||||
:disabled="isBalanceEmpty"
|
:disabled="isBalanceEmpty"
|
||||||
:model-value="form.targetCommunity"
|
:model-value="form.targetCommunity"
|
||||||
@update:model-value="updateField($event, 'targetCommunity')"
|
@update:model-value="updateField($event, 'targetCommunity')"
|
||||||
|
@communitiesLoaded="setCommunities"
|
||||||
/>
|
/>
|
||||||
</BCol>
|
</BCol>
|
||||||
</BRow>
|
</BRow>
|
||||||
@ -62,7 +63,7 @@
|
|||||||
:label="$t('form.recipient')"
|
:label="$t('form.recipient')"
|
||||||
:placeholder="$t('form.identifier')"
|
:placeholder="$t('form.identifier')"
|
||||||
:rules="validationSchema.fields.identifier"
|
:rules="validationSchema.fields.identifier"
|
||||||
:disabled="isBalanceEmpty"
|
:disabled="isBalanceEmpty || isCommunitiesEmpty"
|
||||||
:disable-smart-valid-state="disableSmartValidState"
|
:disable-smart-valid-state="disableSmartValidState"
|
||||||
@update:model-value="updateField"
|
@update:model-value="updateField"
|
||||||
/>
|
/>
|
||||||
@ -171,6 +172,7 @@ const props = defineProps({
|
|||||||
const entityDataToForm = computed(() => ({ ...props }))
|
const entityDataToForm = computed(() => ({ ...props }))
|
||||||
const form = reactive({ ...entityDataToForm.value })
|
const form = reactive({ ...entityDataToForm.value })
|
||||||
const disableSmartValidState = ref(false)
|
const disableSmartValidState = ref(false)
|
||||||
|
const communities = ref([])
|
||||||
|
|
||||||
const emit = defineEmits(['set-transaction'])
|
const emit = defineEmits(['set-transaction'])
|
||||||
|
|
||||||
@ -191,6 +193,10 @@ const userIdentifier = computed(() => {
|
|||||||
return null
|
return null
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function setCommunities(returnedCommunities) {
|
||||||
|
communities.value = returnedCommunities
|
||||||
|
}
|
||||||
|
|
||||||
const validationSchema = computed(() => {
|
const validationSchema = computed(() => {
|
||||||
const amountSchema = number()
|
const amountSchema = number()
|
||||||
.required()
|
.required()
|
||||||
@ -214,7 +220,29 @@ const validationSchema = computed(() => {
|
|||||||
return object({
|
return object({
|
||||||
memo: memoSchema,
|
memo: memoSchema,
|
||||||
amount: amountSchema,
|
amount: amountSchema,
|
||||||
identifier: identifierSchema,
|
identifier: identifierSchema.test(
|
||||||
|
'community-is-reachable',
|
||||||
|
'form.validation.identifier.communityIsReachable',
|
||||||
|
(value) => {
|
||||||
|
const parts = value.split('/')
|
||||||
|
// early exit if no community id is in identifier string
|
||||||
|
if (parts.length !== 2) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
const com = communities.value.find((community) => {
|
||||||
|
return (
|
||||||
|
community.uuid === parts[0] ||
|
||||||
|
community.name === parts[0] ||
|
||||||
|
community.url === parts[0]
|
||||||
|
)
|
||||||
|
})
|
||||||
|
if (com) {
|
||||||
|
form.targetCommunity = com
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
},
|
||||||
|
),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// don't need identifier schema if it is a transaction link or identifier was set via url
|
// don't need identifier schema if it is a transaction link or identifier was set via url
|
||||||
@ -224,7 +252,6 @@ const validationSchema = computed(() => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const formIsInvalid = computed(() => !validationSchema.value.isValidSync(form))
|
const formIsInvalid = computed(() => !validationSchema.value.isValidSync(form))
|
||||||
|
|
||||||
const updateField = (newValue, name) => {
|
const updateField = (newValue, name) => {
|
||||||
@ -234,6 +261,7 @@ const updateField = (newValue, name) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isBalanceEmpty = computed(() => props.balance <= 0)
|
const isBalanceEmpty = computed(() => props.balance <= 0)
|
||||||
|
const isCommunitiesEmpty = computed(() => communities.value.length === 0)
|
||||||
|
|
||||||
const { result: userResult, error: userError } = useQuery(
|
const { result: userResult, error: userError } = useQuery(
|
||||||
user,
|
user,
|
||||||
@ -260,6 +288,13 @@ watch(userError, (error) => {
|
|||||||
|
|
||||||
function onSubmit() {
|
function onSubmit() {
|
||||||
const transformedForm = validationSchema.value.cast(form)
|
const transformedForm = validationSchema.value.cast(form)
|
||||||
|
const parts = transformedForm.identifier.split('/')
|
||||||
|
if (parts.length === 2) {
|
||||||
|
transformedForm.identifier = parts[1]
|
||||||
|
transformedForm.targetCommunity = communities.value.find((com) => {
|
||||||
|
return com.uuid === parts[0] || com.name === parts[0] || com.url === parts[0]
|
||||||
|
})
|
||||||
|
}
|
||||||
emit('set-transaction', {
|
emit('set-transaction', {
|
||||||
...transformedForm,
|
...transformedForm,
|
||||||
selected: radioSelected.value,
|
selected: radioSelected.value,
|
||||||
|
|||||||
9
frontend/src/graphql/communities.graphql
Normal file
9
frontend/src/graphql/communities.graphql
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
query reachableCommunities {
|
||||||
|
reachableCommunities {
|
||||||
|
foreign
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
description
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -91,19 +91,6 @@ export const listGDTEntriesQuery = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export const selectCommunities = gql`
|
|
||||||
query {
|
|
||||||
communities {
|
|
||||||
uuid
|
|
||||||
name
|
|
||||||
description
|
|
||||||
foreign
|
|
||||||
url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
export const queryOptIn = gql`
|
export const queryOptIn = gql`
|
||||||
query ($optIn: String!) {
|
query ($optIn: String!) {
|
||||||
queryOptIn(optIn: $optIn)
|
queryOptIn(optIn: $optIn)
|
||||||
|
|||||||
@ -4,3 +4,9 @@ fragment userFields on User {
|
|||||||
lastName
|
lastName
|
||||||
alias
|
alias
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query user($identifier: String!, $communityIdentifier: String) {
|
||||||
|
user(identifier: $identifier, communityIdentifier: $communityIdentifier) {
|
||||||
|
...userFields
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -231,6 +231,7 @@
|
|||||||
},
|
},
|
||||||
"gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein.",
|
"gddSendAmount": "Das Feld {_field_} muss eine Zahl zwischen {min} und {max} mit höchstens zwei Nachkommastellen sein.",
|
||||||
"identifier": {
|
"identifier": {
|
||||||
|
"communityIsReachable": "Community nicht gefunden oder nicht erreichbar!",
|
||||||
"required": "Der Empfänger ist ein Pflichtfeld.",
|
"required": "Der Empfänger ist ein Pflichtfeld.",
|
||||||
"typeError": "Der Empfänger muss eine Email, ein Nutzernamen oder eine Gradido ID sein."
|
"typeError": "Der Empfänger muss eine Email, ein Nutzernamen oder eine Gradido ID sein."
|
||||||
},
|
},
|
||||||
|
|||||||
@ -231,6 +231,7 @@
|
|||||||
},
|
},
|
||||||
"gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits after the decimal point.",
|
"gddSendAmount": "The {_field_} field must be a number between {min} and {max} with at most two digits after the decimal point.",
|
||||||
"identifier": {
|
"identifier": {
|
||||||
|
"communityIsReachable": "Community not found our not reachable!",
|
||||||
"required": "The recipient is a required field.",
|
"required": "The recipient is a required field.",
|
||||||
"typeError": "The recipient must be an email, a username or a Gradido ID."
|
"typeError": "The recipient must be an email, a username or a Gradido ID."
|
||||||
},
|
},
|
||||||
|
|||||||
@ -185,6 +185,11 @@
|
|||||||
"to1": "para",
|
"to1": "para",
|
||||||
"validation": {
|
"validation": {
|
||||||
"gddSendAmount": "El campo {_field_} debe ser un número entre {min} y {max} con un máximo de dos decimales",
|
"gddSendAmount": "El campo {_field_} debe ser un número entre {min} y {max} con un máximo de dos decimales",
|
||||||
|
"identifier": {
|
||||||
|
"communityIsReachable": "Comunidad no encontrada o no alcanzable!",
|
||||||
|
"required": "El destinatario es un campo obligatorio.",
|
||||||
|
"typeError": "El destinatario debe ser un email, un nombre de usuario o un Gradido ID."
|
||||||
|
},
|
||||||
"is-not": "No es posible transferirte Gradidos a ti mismo",
|
"is-not": "No es posible transferirte Gradidos a ti mismo",
|
||||||
"requiredField": "El campo {fieldName} es obligatorio",
|
"requiredField": "El campo {fieldName} es obligatorio",
|
||||||
"usernmae-regex": "El nombre de usuario debe comenzar con una letra seguida de al menos dos caracteres alfanuméricos.",
|
"usernmae-regex": "El nombre de usuario debe comenzar con una letra seguida de al menos dos caracteres alfanuméricos.",
|
||||||
|
|||||||
@ -191,6 +191,13 @@
|
|||||||
"validation": {
|
"validation": {
|
||||||
"gddCreationTime": "Le champ {_field_} doit comprendre un nombre entre {min} et {max} avec un maximum de une décimale.",
|
"gddCreationTime": "Le champ {_field_} doit comprendre un nombre entre {min} et {max} avec un maximum de une décimale.",
|
||||||
"gddSendAmount": "Le champ {_field_} doit comprendre un nombre entre {min} et {max} avec un maximum de deux chiffres après la virgule",
|
"gddSendAmount": "Le champ {_field_} doit comprendre un nombre entre {min} et {max} avec un maximum de deux chiffres après la virgule",
|
||||||
|
"identifier": {
|
||||||
|
"communityIsReachable": "Communauté non joignable!",
|
||||||
|
"communityIsReachable.communityNotFound": "Communauté non trouvée!",
|
||||||
|
"communityIsReachable.communityNotReachable": "Communauté non joignable!",
|
||||||
|
"required": "Le destinataire est un champ obligatoire.",
|
||||||
|
"typeError": "Le destinataire doit être un email, un nom d'utilisateur ou un Gradido ID."
|
||||||
|
},
|
||||||
"is-not": "Vous ne pouvez pas vous envoyer de Gradido à vous-même",
|
"is-not": "Vous ne pouvez pas vous envoyer de Gradido à vous-même",
|
||||||
"requiredField": "Le champ {fieldName} est obligatoire",
|
"requiredField": "Le champ {fieldName} est obligatoire",
|
||||||
"usernmae-regex": "Le nom d'utilisateur doit commencer par une lettre, suivi d'au moins deux caractères alphanumériques.",
|
"usernmae-regex": "Le nom d'utilisateur doit commencer par une lettre, suivi d'au moins deux caractères alphanumériques.",
|
||||||
|
|||||||
@ -185,6 +185,11 @@
|
|||||||
"to1": "aan",
|
"to1": "aan",
|
||||||
"validation": {
|
"validation": {
|
||||||
"gddSendAmount": "Het veld {_field_} moet een getal tussen {min} en {max} met maximaal twee cijfers achter de komma zijn",
|
"gddSendAmount": "Het veld {_field_} moet een getal tussen {min} en {max} met maximaal twee cijfers achter de komma zijn",
|
||||||
|
"identifier": {
|
||||||
|
"communityIsReachable": "Community niet gevonden of niet bereikbaar!",
|
||||||
|
"required": "Ontvanger is een verplicht veld.",
|
||||||
|
"typeError": "Ontvanger moet een email, een gebruikersnaam of een Gradido ID zijn."
|
||||||
|
},
|
||||||
"is-not": "Je kunt geen Gradidos aan jezelf overmaken",
|
"is-not": "Je kunt geen Gradidos aan jezelf overmaken",
|
||||||
"requiredField": "{fieldName} is verplicht",
|
"requiredField": "{fieldName} is verplicht",
|
||||||
"usernmae-regex": "De gebruikersnaam moet met een letter beginnen, waarop minimaal twee alfanumerieke tekens dienen te volgen.",
|
"usernmae-regex": "De gebruikersnaam moet met een letter beginnen, waarop minimaal twee alfanumerieke tekens dienen te volgen.",
|
||||||
|
|||||||
@ -28,10 +28,21 @@ export const memo = string()
|
|||||||
|
|
||||||
export const identifier = string()
|
export const identifier = string()
|
||||||
.required('form.validation.identifier.required')
|
.required('form.validation.identifier.required')
|
||||||
|
.test(
|
||||||
|
'valid-parts',
|
||||||
|
'form.validation.identifier.partsError',
|
||||||
|
(value) => (value.match(/\//g) || []).length <= 1, // allow only one or zero slash
|
||||||
|
)
|
||||||
.test('valid-identifier', 'form.validation.identifier.typeError', (value) => {
|
.test('valid-identifier', 'form.validation.identifier.typeError', (value) => {
|
||||||
const isEmail = !!EMAIL_REGEX.test(value)
|
let userPart = value
|
||||||
const isUsername = !!value.match(USERNAME_REGEX)
|
const parts = value.split('/')
|
||||||
|
if (parts.length === 2) {
|
||||||
|
userPart = parts[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
const isEmail = !!EMAIL_REGEX.test(userPart)
|
||||||
|
const isUsername = !!userPart.match(USERNAME_REGEX)
|
||||||
// TODO: use valibot and rules from shared
|
// TODO: use valibot and rules from shared
|
||||||
const isGradidoId = validateUuid(value) && versionUuid(value) === 4
|
const isGradidoId = validateUuid(userPart) && versionUuid(userPart) === 4
|
||||||
return isEmail || isUsername || isGradidoId
|
return isEmail || isUsername || isGradidoId
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user