mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into apollo_createTransactions_without_signation
This commit is contained in:
commit
66e4d86ae0
64
README.md
64
README.md
@ -8,33 +8,73 @@ 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
|
||||||
|
docker-compose up
|
||||||
|
```
|
||||||
|
### Additional Build options
|
||||||
|
If you want to build for production you can do this aswell:
|
||||||
|
```bash
|
||||||
|
docker-compose -f docker-compose.yml up
|
||||||
|
```
|
||||||
|
|
||||||
```bash
|
## Services defined in this package
|
||||||
docker-compose up
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Or run docker compose in production build
|
- [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
|
||||||
|
|
||||||
```bash
|
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.
|
||||||
docker-compose -f docker-compose.yml up
|
|
||||||
```
|
### 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
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,4 @@ import { ArgsType, Field } from 'type-graphql'
|
|||||||
export default class CheckUsernameArgs {
|
export default class CheckUsernameArgs {
|
||||||
@Field(() => String)
|
@Field(() => String)
|
||||||
username: string
|
username: string
|
||||||
|
|
||||||
@Field(() => Number, { nullable: true })
|
|
||||||
groupId?: number
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,21 +0,0 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
|
||||||
import { ObjectType, Field } from 'type-graphql'
|
|
||||||
|
|
||||||
@ObjectType()
|
|
||||||
export class CheckUsernameResponse {
|
|
||||||
constructor(json: any) {
|
|
||||||
this.state = json.state
|
|
||||||
this.msg = json.msg
|
|
||||||
this.groupId = json.group_id
|
|
||||||
}
|
|
||||||
|
|
||||||
@Field(() => String)
|
|
||||||
state: string
|
|
||||||
|
|
||||||
@Field(() => String)
|
|
||||||
msg?: string
|
|
||||||
|
|
||||||
@Field(() => Number)
|
|
||||||
groupId?: number
|
|
||||||
}
|
|
||||||
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
import { Resolver, Query, Args, Arg, Authorized, Ctx, UseMiddleware, Mutation } from 'type-graphql'
|
import { Resolver, Query, Args, Arg, Authorized, Ctx, UseMiddleware, Mutation } from 'type-graphql'
|
||||||
import { from_hex as fromHex } from 'libsodium-wrappers'
|
import { from_hex as fromHex } from 'libsodium-wrappers'
|
||||||
|
import { getCustomRepository } from 'typeorm'
|
||||||
import CONFIG from '../../config'
|
import CONFIG from '../../config'
|
||||||
import { CheckUsernameResponse } from '../model/CheckUsernameResponse'
|
|
||||||
import { LoginViaVerificationCode } from '../model/LoginViaVerificationCode'
|
import { LoginViaVerificationCode } from '../model/LoginViaVerificationCode'
|
||||||
import { SendPasswordResetEmailResponse } from '../model/SendPasswordResetEmailResponse'
|
import { SendPasswordResetEmailResponse } from '../model/SendPasswordResetEmailResponse'
|
||||||
import { UpdateUserInfosResponse } from '../model/UpdateUserInfosResponse'
|
import { UpdateUserInfosResponse } from '../model/UpdateUserInfosResponse'
|
||||||
@ -22,10 +22,10 @@ import {
|
|||||||
klicktippNewsletterStateMiddleware,
|
klicktippNewsletterStateMiddleware,
|
||||||
} from '../../middleware/klicktippMiddleware'
|
} from '../../middleware/klicktippMiddleware'
|
||||||
import { CheckEmailResponse } from '../model/CheckEmailResponse'
|
import { CheckEmailResponse } from '../model/CheckEmailResponse'
|
||||||
import { getCustomRepository } from 'typeorm'
|
|
||||||
import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository'
|
import { UserSettingRepository } from '../../typeorm/repository/UserSettingRepository'
|
||||||
import { Setting } from '../enum/Setting'
|
import { Setting } from '../enum/Setting'
|
||||||
import { UserRepository } from '../../typeorm/repository/User'
|
import { UserRepository } from '../../typeorm/repository/User'
|
||||||
|
import { LoginUser } from '@entity/LoginUser'
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class UserResolver {
|
export class UserResolver {
|
||||||
@ -275,15 +275,27 @@ export class UserResolver {
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => CheckUsernameResponse)
|
@Query(() => Boolean)
|
||||||
async checkUsername(
|
async checkUsername(@Args() { username }: CheckUsernameArgs): Promise<boolean> {
|
||||||
@Args() { username, groupId = 1 }: CheckUsernameArgs,
|
// Username empty?
|
||||||
): Promise<CheckUsernameResponse> {
|
if (username === '') {
|
||||||
const response = await apiGet(
|
throw new Error('Username must be set.')
|
||||||
CONFIG.LOGIN_API_URL + `checkUsername?username=${username}&group_id=${groupId}`,
|
}
|
||||||
)
|
|
||||||
if (!response.success) throw new Error(response.data)
|
// Do we fullfil the minimum character length?
|
||||||
return new CheckUsernameResponse(response.data)
|
const MIN_CHARACTERS_USERNAME = 2
|
||||||
|
if (username.length < MIN_CHARACTERS_USERNAME) {
|
||||||
|
throw new Error(`Username must be at minimum ${MIN_CHARACTERS_USERNAME} characters long.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const usersFound = await LoginUser.count({ username })
|
||||||
|
|
||||||
|
// Username already present?
|
||||||
|
if (usersFound !== 0) {
|
||||||
|
throw new Error(`Username "${username}" already taken.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@Query(() => CheckEmailResponse)
|
@Query(() => CheckEmailResponse)
|
||||||
|
|||||||
56
database/entity/0003-login_server_tables/LoginUser.ts
Normal file
56
database/entity/0003-login_server_tables/LoginUser.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
|
||||||
|
|
||||||
|
// Moriz: I do not like the idea of having two user tables
|
||||||
|
@Entity('login_users')
|
||||||
|
export class LoginUser extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Column({ length: 191, unique: true })
|
||||||
|
email: string
|
||||||
|
|
||||||
|
@Column({ name: 'first_name', length: 150 })
|
||||||
|
firstName: string
|
||||||
|
|
||||||
|
@Column({ name: 'last_name', length: 255, default: '' })
|
||||||
|
lastName: string
|
||||||
|
|
||||||
|
@Column({ length: 255, default: '' })
|
||||||
|
username: string
|
||||||
|
|
||||||
|
@Column({ default: '' })
|
||||||
|
description: string
|
||||||
|
|
||||||
|
@Column({ type: 'bigint', default: 0, unsigned: true })
|
||||||
|
password: string
|
||||||
|
|
||||||
|
@Column({ name: 'pubkey', type: 'binary', length: 32, default: null, nullable: true })
|
||||||
|
pubKey: Buffer
|
||||||
|
|
||||||
|
@Column({ name: 'privkey', type: 'binary', length: 80, default: null, nullable: true })
|
||||||
|
privKey: Buffer
|
||||||
|
|
||||||
|
@Column({ name: 'email_hash', type: 'binary', length: 32, default: null, nullable: true })
|
||||||
|
emailHash: Buffer
|
||||||
|
|
||||||
|
@Column({ name: 'created', default: () => 'CURRENT_TIMESTAMP' })
|
||||||
|
createdAt: Date
|
||||||
|
|
||||||
|
@Column({ name: 'email_checked', default: 0 })
|
||||||
|
emailChecked: boolean
|
||||||
|
|
||||||
|
@Column({ name: 'passphrase_shown', default: 0 })
|
||||||
|
passphraseShown: boolean
|
||||||
|
|
||||||
|
@Column({ length: 4, default: 'de' })
|
||||||
|
language: string
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
disabled: boolean
|
||||||
|
|
||||||
|
@Column({ name: 'group_id', default: 0, unsigned: true })
|
||||||
|
groupId: number
|
||||||
|
|
||||||
|
@Column({ name: 'publisher_id', default: 0 })
|
||||||
|
publisherId: number
|
||||||
|
}
|
||||||
1
database/entity/LoginUser.ts
Normal file
1
database/entity/LoginUser.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { LoginUser } from './0003-login_server_tables/LoginUser'
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { Balance } from './Balance'
|
import { Balance } from './Balance'
|
||||||
|
import { LoginUser } from './LoginUser'
|
||||||
import { Migration } from './Migration'
|
import { Migration } from './Migration'
|
||||||
import { Transaction } from './Transaction'
|
import { Transaction } from './Transaction'
|
||||||
import { TransactionCreation } from './TransactionCreation'
|
import { TransactionCreation } from './TransactionCreation'
|
||||||
@ -9,6 +10,7 @@ import { UserTransaction } from './UserTransaction'
|
|||||||
|
|
||||||
export const entities = [
|
export const entities = [
|
||||||
Balance,
|
Balance,
|
||||||
|
LoginUser,
|
||||||
Migration,
|
Migration,
|
||||||
Transaction,
|
Transaction,
|
||||||
TransactionCreation,
|
TransactionCreation,
|
||||||
|
|||||||
@ -75,9 +75,7 @@ export const sendResetPasswordEmail = gql`
|
|||||||
|
|
||||||
export const checkUsername = gql`
|
export const checkUsername = gql`
|
||||||
query($username: String!) {
|
query($username: String!) {
|
||||||
checkUsername(username: $username) {
|
checkUsername(username: $username)
|
||||||
state
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
|||||||
@ -59,7 +59,7 @@ export const loadAllRules = (i18nCallback) => {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
return result.data.checkUsername.state === 'success'
|
return result.data.checkUsername
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
return false
|
return false
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user