Merge branch 'master' into apollo_createTransactions_without_signation

This commit is contained in:
Moriz Wahl 2021-11-04 13:57:19 +01:00
commit ee12eb15a4
18 changed files with 283 additions and 75 deletions

View File

@ -344,7 +344,7 @@ jobs:
report_name: Coverage Frontend
type: lcov
result_path: ./coverage/lcov.info
min_coverage: 83
min_coverage: 85
token: ${{ github.token }}
##############################################################################
@ -353,7 +353,7 @@ jobs:
unit_test_backend:
name: Unit tests - Backend
runs-on: ubuntu-latest
needs: [build_test_backend]
needs: [build_test_backend,build_test_mariadb]
steps:
##########################################################################
# CHECKOUT CODE ##########################################################
@ -363,6 +363,13 @@ jobs:
##########################################################################
# DOWNLOAD DOCKER IMAGES #################################################
##########################################################################
- name: Download Docker Image (Mariadb)
uses: actions/download-artifact@v2
with:
name: docker-mariadb-test
path: /tmp
- name: Load Docker Image
run: docker load < /tmp/mariadb.tar
- name: Download Docker Image (Backend)
uses: actions/download-artifact@v2
with:
@ -373,10 +380,11 @@ jobs:
##########################################################################
# UNIT TESTS BACKEND #####################################################
##########################################################################
- name: backend | Unit tests
run: |
docker run -v ~/coverage:/app/coverage --rm gradido/backend:test yarn run test
cp -r ~/coverage ./coverage
- name: backend | docker-compose
run: docker-compose -f docker-compose.yml -f docker-compose.test.yml up --detach --no-deps mariadb database
- name: backend Unit tests | test
run: cd database && yarn && cd ../backend && yarn && yarn test
# run: docker-compose -f docker-compose.yml -f docker-compose.test.yml exec -T backend yarn test
##########################################################################
# COVERAGE CHECK BACKEND #################################################
##########################################################################
@ -385,8 +393,8 @@ jobs:
with:
report_name: Coverage Backend
type: lcov
result_path: ./coverage/lcov.info
min_coverage: 1
result_path: ./backend/coverage/lcov.info
min_coverage: 45
token: ${{ github.token }}
##############################################################################

7
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"recommendations": [
"streetsidesoftware.code-spell-checker",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}

View File

@ -85,7 +85,7 @@ RUN cd ../database && yarn run build
FROM build as test
# Run command
CMD /bin/sh -c "yarn run dev"
CMD /bin/sh -c "yarn run start"
##################################################################################
# PRODUCTION (Does contain only "binary"- and static-files to reduce image size) #

View File

@ -13,11 +13,12 @@
"start": "node build/index.js",
"dev": "nodemon -w src --ext ts --exec ts-node src/index.ts",
"lint": "eslint . --ext .js,.ts",
"test": "jest --coverage"
"test": "jest --runInBand --coverage "
},
"dependencies": {
"@types/jest": "^27.0.2",
"apollo-server-express": "^2.25.2",
"apollo-server-testing": "^2.25.2",
"axios": "^0.21.1",
"class-validator": "^0.13.1",
"cors": "^2.8.5",

View File

@ -0,0 +1,123 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { createTestClient } from 'apollo-server-testing'
import createServer from '../../server/createServer'
import CONFIG from '../../config'
jest.mock('../../config')
let query: any
// to do: We need a setup for the tests that closes the connection
let con: any
beforeAll(async () => {
const server = await createServer({})
con = server.con
query = createTestClient(server.apollo).query
})
afterAll(async () => {
await con.close()
})
describe('CommunityResolver', () => {
const getCommunityInfoQuery = `
query {
getCommunityInfo {
name
description
url
registerUrl
}
}
`
const communities = `
query {
communities {
id
name
url
description
registerUrl
}
}
`
describe('getCommunityInfo', () => {
it('returns the default values', async () => {
expect(query({ query: getCommunityInfoQuery })).resolves.toMatchObject({
data: {
getCommunityInfo: {
name: 'Gradido Entwicklung',
description: 'Die lokale Entwicklungsumgebung von Gradido.',
url: 'http://localhost/vue/',
registerUrl: 'http://localhost/vue/register',
},
},
})
})
})
describe('communities', () => {
describe('PRODUCTION = false', () => {
beforeEach(() => {
CONFIG.PRODUCTION = false
})
it('returns three communities', async () => {
expect(query({ query: communities })).resolves.toMatchObject({
data: {
communities: [
{
id: 1,
name: 'Gradido Entwicklung',
description: 'Die lokale Entwicklungsumgebung von Gradido.',
url: 'http://localhost/vue/',
registerUrl: 'http://localhost/vue/register-community',
},
{
id: 2,
name: 'Gradido Staging',
description: 'Der Testserver der Gradido-Akademie.',
url: 'https://stage1.gradido.net/vue/',
registerUrl: 'https://stage1.gradido.net/vue/register-community',
},
{
id: 3,
name: 'Gradido-Akademie',
description: 'Freies Institut für Wirtschaftsbionik.',
url: 'https://gradido.net',
registerUrl: 'https://gdd1.gradido.com/vue/register-community',
},
],
},
})
})
})
describe('PRODUCTION = true', () => {
beforeEach(() => {
CONFIG.PRODUCTION = true
})
it('returns one community', async () => {
expect(query({ query: communities })).resolves.toMatchObject({
data: {
communities: [
{
id: 3,
name: 'Gradido-Akademie',
description: 'Freies Institut für Wirtschaftsbionik.',
url: 'https://gradido.net',
registerUrl: 'https://gdd1.gradido.com/vue/register-community',
},
],
},
})
})
})
})
})

View File

@ -6,7 +6,7 @@ import isAuthorized from './directive/isAuthorized'
const schema = async (): Promise<GraphQLSchema> => {
return buildSchema({
resolvers: [path.join(__dirname, 'resolver', `*.{js,ts}`)],
resolvers: [path.join(__dirname, 'resolver', `!(*.test).{js,ts}`)],
authChecker: isAuthorized,
})
}

View File

@ -1,64 +1,14 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import 'reflect-metadata'
import 'module-alias/register'
import express from 'express'
import { ApolloServer } from 'apollo-server-express'
import createServer from './server/createServer'
// config
import CONFIG from './config'
// database
import connection from './typeorm/connection'
import getDBVersion from './typeorm/getDBVersion'
// server
import cors from './server/cors'
import context from './server/context'
import plugins from './server/plugins'
// graphql
import schema from './graphql/schema'
// TODO implement
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
const DB_VERSION = '0004-login_server_data'
async function main() {
// open mysql connection
const con = await connection()
if (!con || !con.isConnected) {
throw new Error(`Couldn't open connection to database`)
}
const { app } = await createServer()
// check for correct database version
const dbVersion = await getDBVersion()
if (!dbVersion || dbVersion.indexOf(DB_VERSION) === -1) {
throw new Error(
`Wrong database version - the backend requires '${DB_VERSION}' but found '${
dbVersion || 'None'
}'`,
)
}
// Express Server
const server = express()
// cors
server.use(cors)
// Apollo Server
const apollo = new ApolloServer({
schema: await schema(),
playground: CONFIG.GRAPHIQL,
context,
plugins,
})
apollo.applyMiddleware({ app: server })
// Start Server
server.listen(CONFIG.PORT, () => {
app.listen(CONFIG.PORT, () => {
// eslint-disable-next-line no-console
console.log(`Server is running at http://localhost:${CONFIG.PORT}`)
if (CONFIG.GRAPHIQL) {

View File

@ -0,0 +1,64 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import 'reflect-metadata'
import 'module-alias/register'
import { ApolloServer } from 'apollo-server-express'
import express from 'express'
// database
import connection from '../typeorm/connection'
import getDBVersion from '../typeorm/getDBVersion'
// server
import cors from './cors'
import serverContext from './context'
import plugins from './plugins'
// config
import CONFIG from '../config'
// graphql
import schema from '../graphql/schema'
// TODO implement
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
const DB_VERSION = '0004-login_server_data'
const createServer = async (context: any = serverContext): Promise<any> => {
// open mysql connection
const con = await connection()
if (!con || !con.isConnected) {
throw new Error(`Couldn't open connection to database`)
}
// check for correct database version
const dbVersion = await getDBVersion()
if (!dbVersion || dbVersion.indexOf(DB_VERSION) === -1) {
throw new Error(
`Wrong database version - the backend requires '${DB_VERSION}' but found '${
dbVersion || 'None'
}'`,
)
}
// Express Server
const app = express()
// cors
app.use(cors)
// Apollo Server
const apollo = new ApolloServer({
schema: await schema(),
playground: CONFIG.GRAPHIQL,
context,
plugins,
})
apollo.applyMiddleware({ app })
return { apollo, app, con }
}
export default createServer

View File

@ -1366,6 +1366,13 @@ apollo-server-plugin-base@^0.13.0:
dependencies:
apollo-server-types "^0.9.0"
apollo-server-testing@^2.25.2:
version "2.25.2"
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.25.2.tgz#0043e98b1a03720352e94b409215fb4782ae2e50"
integrity sha512-HjQV9wPbi/ZqpRbyyhNwCbaDnfjDM0hTRec5TOoOjurEZ/vh4hTPHwGkDZx3kbcWowhGxe2qoHM6KANSB/SxuA==
dependencies:
apollo-server-core "^2.25.2"
apollo-server-types@^0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.9.0.tgz#ccf550b33b07c48c72f104fbe2876232b404848b"

View File

@ -2,6 +2,26 @@ version: "3.4"
services:
########################################################
# BACKEND ##############################################
########################################################
backend:
image: gradido/backend:test
build:
target: test
networks:
- external-net
- internal-net
environment:
- NODE_ENV="test"
- DB_HOST=mariadb
########################################################
# DATABASE #############################################
########################################################
database:
restart: always # this is very dangerous, but worth a test for the delayed mariadb startup at first run
#########################################################
## MARIADB ##############################################
#########################################################
@ -15,10 +35,11 @@ services:
- MARIADB_USER=root
networks:
- internal-net
- external-net
ports:
- 3306:3306
volumes:
- db_test_vol:/var/lib/mysql
- db_test_vol:/var/lib/mysql
#########################################################
## LOGIN SERVER #########################################

BIN
docu/Gradido-Admin.epgz Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -9,8 +9,9 @@ module.exports = {
],
// coverageReporters: ['lcov', 'text'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'\\.(css|less)$': 'identity-obj-proxy',
'\\.(scss)$': '<rootDir>/src/assets/mocks/styleMock.js',
'^@/(.*)$': '<rootDir>/src/$1',
},
transform: {
'^.+\\.vue$': 'vue-jest',

View File

@ -0,0 +1 @@
module.exports = {}

View File

@ -0,0 +1,25 @@
import dashboardPlugin from './dashboard-plugin.js'
import Vue from 'vue'
import GlobalComponents from './globalComponents'
import GlobalDirectives from './globalDirectives'
jest.mock('./globalComponents')
jest.mock('./globalDirectives')
jest.mock('vue')
const vueUseMock = jest.fn()
Vue.use = vueUseMock
describe('dashboard plugin', () => {
dashboardPlugin.install(Vue)
it('installs the global components', () => {
expect(vueUseMock).toBeCalledWith(GlobalComponents)
})
it('installs the global directives', () => {
expect(vueUseMock).toBeCalledWith(GlobalDirectives)
})
})

View File

@ -69,7 +69,7 @@ namespace controller {
using namespace Poco::Data::Keywords;
Poco::Data::Statement select(session);
select << "SELECT id, first_name, last_name, email, username, description, pubkey, created, email_checked, disabled, group_id FROM " << db->getTableName();
select << "SELECT id, first_name, last_name, email, username, description, pubkey, created, email_checked, disabled, group_id, publisher_id FROM " << db->getTableName();
select << " where email_checked = 0 ";
select, into(resultFromDB);
if (searchString != "") {

View File

@ -74,7 +74,8 @@ enum PageState {
{
//mSession->finalizeTransaction(false, true);
//
if(!transaction.isNull() && transaction->getModel()->getUserId() == user_model->getID())
if(!transaction.isNull() &&
(transaction_body->isCreation() || transaction->getModel()->getUserId() == user_model->getID()))
{
if(pt->removeTask(transaction)) {
transaction->deleteFromDB();
@ -150,7 +151,7 @@ enum PageState {
transaction_body = transaction->getTransactionBody();
// user can only delete there own transactions
// TODO: Auto timeout for community transactions
if(transaction->getModel()->getUserId() == user_model->getID()) {
if(transaction_body->isCreation() || transaction->getModel()->getUserId() == user_model->getID()) {
transaction_removeable = true;
}
}
@ -338,20 +339,19 @@ enum PageState {
<%= gettext("Transaktion unterzeichnen") %>
</button>
<% } %>
<button type="submit" class="form-button button-cancel" name="skip" value="skip">
<i class="material-icons-outlined">debug-step-over</i>
<%= gettext("Transaktion &uuml;berspringen") %>
</button>
<% if(transaction_removeable) { %>
<button type="submit" class="form-button button-cancel" name="abort" value="abort">
<i class="material-icons-outlined">delete</i>
<%= gettext("Transaktion verwerfen") %>
</button>
<% } else { %>
<button type="submit" class="form-button button-cancel" name="skip" value="skip">
<i class="material-icons-outlined">debug-step-over</i>
<%= gettext("Transaktion &uuml;berspringen") %>
</button>
<% } %>
</form>
<% } %>
</div>
</div>
</div>
<%@ include file="include/footer_chr.cpsp" %>
<%@ include file="include/footer_chr.cpsp" %>