Merge branch 'master' into login_call_createUser

This commit is contained in:
elweyn 2021-11-04 14:15:08 +01:00
commit 97d08c95a3
19 changed files with 336 additions and 88 deletions

View File

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

@ -8,34 +8,74 @@ The Gradido model can create global prosperity and peace
The Corona crisis has fundamentally changed our world within a very short time. The Corona crisis has fundamentally changed our world within a very short time.
The dominant financial system threatens to fail around the globe, followed by mass insolvencies, record unemployment and abject poverty. Only with a sustainable new monetary system can humanity master these challenges of the 21st century. The Gradido Academy for Bionic Economy has developed such a system. The dominant financial system threatens to fail around the globe, followed by mass insolvencies, record unemployment and abject poverty. Only with a sustainable new monetary system can humanity master these challenges of the 21st century. The Gradido Academy for Bionic Economy has developed such a system.
Find out more about the Project on its [Website](https://gradido.net/). It is offering vast resources about the idea. The remaining document will discuss the gradido software only.
## Software requirements ## Software requirements
Currently we only support `docker` as environment to run all services, since many different programming languages and frameworks are used. Currently we only support `docker` install instructions to run all services, since many different programming languages and frameworks are used.
- [docker](https://www.docker.com/) - [docker](https://www.docker.com/)
- [docker-compose]
### For Arch Linux
Install the required packages:
```bash
sudo pacman -S docker
sudo pacman -S docker-compose
```
Add group `docker` and then your user to it in order to allow you to run docker without sudo
```bash
sudo groupadd docker # may already exist `groupadd: group 'docker' already exists`
sudo usermod -aG docker $USER
groups # verify you have the group (requires relog)
```
Start the docker service:
```bash
sudo systemctrl start docker
```
## How to run? ## How to run?
1. Clone the repo and pull all submodules ### 1. Clone Sources
Clone the repo and pull all submodules
```bash ```bash
git clone git@github.com:gradido/gradido.git git clone git@github.com:gradido/gradido.git
git submodule update --recursive --init git submodule update --recursive --init
``` ```
2. Run docker compose ### 2. Run docker-compose
1. Run docker compose for the debug build Run docker-compose to bring up the development environment
```bash ```bash
docker-compose up docker-compose up
``` ```
### Additional Build options
2. Or run docker compose in production build If you want to build for production you can do this aswell:
```bash ```bash
docker-compose -f docker-compose.yml up docker-compose -f docker-compose.yml up
``` ```
## Services defined in this package
- [frontend](./frontend) Wallet frontend
- [backend](./backend) GraphQL & Business logic backend
- [mariadb](./mariadb) Database backend
- [login_server](./login_server) User credential storage & business logic backend
- [community_server](./community_server/) Business logic backend
We are currently restructuring the service to reduce dependencies and unify business logic into one place. Furthermore the databases defined for each service will be unified into one.
### Open the wallet
Once you have `docker-compose` up and running, you can open [http://localhost/vue](http://localhost/vue) and create yourself a new wallet account.
## Troubleshooting
| Problem | Issue | Solution | Description |
| ------- | ----- | -------- | ----------- |
| docker-compose raises database connection errors | [#1062](https://github.com/gradido/gradido/issues/1062) | End `ctrl+c` and restart the `docker-compose up` after a successful build | Several Database connection related errors occur in the docker-compose log. |
| Wallet page is empty | [#1063](https://github.com/gradido/gradido/issues/1063) | Accept Cookies and Local Storage in your Browser | The page stays empty when navigating to [http://localhost/vue](http://localhost/vue) |
## Useful Links ## Useful Links
- [Gradido.net](https://gradido.net/) - [Gradido.net](https://gradido.net/)

View File

@ -85,7 +85,7 @@ RUN cd ../database && yarn run build
FROM build as test FROM build as test
# Run command # 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) # # PRODUCTION (Does contain only "binary"- and static-files to reduce image size) #

View File

@ -13,11 +13,12 @@
"start": "node build/index.js", "start": "node build/index.js",
"dev": "nodemon -w src --ext ts --exec ts-node src/index.ts", "dev": "nodemon -w src --ext ts --exec ts-node src/index.ts",
"lint": "eslint . --ext .js,.ts", "lint": "eslint . --ext .js,.ts",
"test": "jest --coverage" "test": "jest --runInBand --coverage "
}, },
"dependencies": { "dependencies": {
"@types/jest": "^27.0.2", "@types/jest": "^27.0.2",
"apollo-server-express": "^2.25.2", "apollo-server-express": "^2.25.2",
"apollo-server-testing": "^2.25.2",
"axios": "^0.21.1", "axios": "^0.21.1",
"class-validator": "^0.13.1", "class-validator": "^0.13.1",
"cors": "^2.8.5", "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> => { const schema = async (): Promise<GraphQLSchema> => {
return buildSchema({ return buildSchema({
resolvers: [path.join(__dirname, 'resolver', `*.{js,ts}`)], resolvers: [path.join(__dirname, 'resolver', `!(*.test).{js,ts}`)],
authChecker: isAuthorized, authChecker: isAuthorized,
}) })
} }

View File

@ -1,64 +1,14 @@
/* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-explicit-any */
import 'reflect-metadata' import createServer from './server/createServer'
import 'module-alias/register'
import express from 'express'
import { ApolloServer } from 'apollo-server-express'
// config // config
import CONFIG from './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() { async function main() {
// open mysql connection const { app } = await createServer()
const con = await connection()
if (!con || !con.isConnected) {
throw new Error(`Couldn't open connection to database`)
}
// check for correct database version app.listen(CONFIG.PORT, () => {
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, () => {
// eslint-disable-next-line no-console // eslint-disable-next-line no-console
console.log(`Server is running at http://localhost:${CONFIG.PORT}`) console.log(`Server is running at http://localhost:${CONFIG.PORT}`)
if (CONFIG.GRAPHIQL) { 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

@ -1328,6 +1328,13 @@ apollo-server-plugin-base@^0.13.0:
dependencies: dependencies:
apollo-server-types "^0.9.0" 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: apollo-server-types@^0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.9.0.tgz" resolved "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.9.0.tgz"

View File

@ -2,6 +2,26 @@ version: "3.4"
services: 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 ############################################## ## MARIADB ##############################################
######################################################### #########################################################
@ -15,6 +35,7 @@ services:
- MARIADB_USER=root - MARIADB_USER=root
networks: networks:
- internal-net - internal-net
- external-net
ports: ports:
- 3306:3306 - 3306:3306
volumes: volumes:

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'], // coverageReporters: ['lcov', 'text'],
moduleNameMapper: { moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
'\\.(css|less)$': 'identity-obj-proxy', '\\.(css|less)$': 'identity-obj-proxy',
'\\.(scss)$': '<rootDir>/src/assets/mocks/styleMock.js',
'^@/(.*)$': '<rootDir>/src/$1',
}, },
transform: { transform: {
'^.+\\.vue$': 'vue-jest', '^.+\\.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; using namespace Poco::Data::Keywords;
Poco::Data::Statement select(session); 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 << " where email_checked = 0 ";
select, into(resultFromDB); select, into(resultFromDB);
if (searchString != "") { if (searchString != "") {

View File

@ -74,7 +74,8 @@ enum PageState {
{ {
//mSession->finalizeTransaction(false, true); //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)) { if(pt->removeTask(transaction)) {
transaction->deleteFromDB(); transaction->deleteFromDB();
@ -150,7 +151,7 @@ enum PageState {
transaction_body = transaction->getTransactionBody(); transaction_body = transaction->getTransactionBody();
// user can only delete there own transactions // user can only delete there own transactions
// TODO: Auto timeout for community 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; transaction_removeable = true;
} }
} }
@ -338,16 +339,15 @@ enum PageState {
<%= gettext("Transaktion unterzeichnen") %> <%= gettext("Transaktion unterzeichnen") %>
</button> </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) { %> <% if(transaction_removeable) { %>
<button type="submit" class="form-button button-cancel" name="abort" value="abort"> <button type="submit" class="form-button button-cancel" name="abort" value="abort">
<i class="material-icons-outlined">delete</i> <i class="material-icons-outlined">delete</i>
<%= gettext("Transaktion verwerfen") %> <%= gettext("Transaktion verwerfen") %>
</button> </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> </form>
<% } %> <% } %>