mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into login_call_resetPassword
This commit is contained in:
commit
bbd54ef607
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -441,7 +441,7 @@ jobs:
|
|||||||
report_name: Coverage Admin Interface
|
report_name: Coverage Admin Interface
|
||||||
type: lcov
|
type: lcov
|
||||||
result_path: ./coverage/lcov.info
|
result_path: ./coverage/lcov.info
|
||||||
min_coverage: 51
|
min_coverage: 53
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|||||||
16
README.md
16
README.md
@ -69,6 +69,22 @@ We are currently restructuring the service to reduce dependencies and unify busi
|
|||||||
|
|
||||||
Once you have `docker-compose` up and running, you can open [http://localhost/vue](http://localhost/vue) and create yourself a new wallet account.
|
Once you have `docker-compose` up and running, you can open [http://localhost/vue](http://localhost/vue) and create yourself a new wallet account.
|
||||||
|
|
||||||
|
## How to release
|
||||||
|
|
||||||
|
A release is tagged on Github by its version number and published as github release. This is done automatically when a new version is defined in the [package.json](./package.json) and merged into master - furthermore we set all our sub-package-versions to the same version as the main package.json version to make version management as simple as possible.
|
||||||
|
Each release is accompanied with release notes automatically generated from the git log which is available as [CHANGELOG.md](./CHANGELOG.md).
|
||||||
|
|
||||||
|
To generate the Changelog and set a new Version you should use the following commands in the main folder
|
||||||
|
```bash
|
||||||
|
git fetch --all
|
||||||
|
yarn release
|
||||||
|
```
|
||||||
|
|
||||||
|
The first command `git fetch --all` will make sure you have all tags previously defined which is required to generate a correct changelog. The second command `yarn release` will execute the changelog tool and set version numbers in the main package and sub-packages. It is required to do `yarn install` before you can use this command.
|
||||||
|
After generating a new version you should commit the changes. This will be the CHANGELOG.md and several package.json files. This commit will be omitted in the changelog.
|
||||||
|
|
||||||
|
Note: The Changelog will be regenerated with all tags on release on the external builder tool, but will not be checked in there. The Changelog on the github release will therefore always be correct, on the repo it might be incorrect due to missing tags when executing the `yarn release` command.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
| Problem | Issue | Solution | Description |
|
| Problem | Issue | Solution | Description |
|
||||||
|
|||||||
@ -43,6 +43,7 @@
|
|||||||
"vue-jest": "^3.0.7",
|
"vue-jest": "^3.0.7",
|
||||||
"vue-moment": "^4.1.0",
|
"vue-moment": "^4.1.0",
|
||||||
"vue-router": "^3.5.3",
|
"vue-router": "^3.5.3",
|
||||||
|
"vue-toasted": "^1.1.28",
|
||||||
"vuex": "^3.6.2",
|
"vuex": "^3.6.2",
|
||||||
"vuex-persistedstate": "^4.1.0"
|
"vuex-persistedstate": "^4.1.0"
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
admin/public/img/brand/green.png
Normal file
BIN
admin/public/img/brand/green.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
@ -3,6 +3,16 @@ import CreationFormular from './CreationFormular.vue'
|
|||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
|
|
||||||
|
const apolloMock = jest.fn().mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
verifyLogin: {
|
||||||
|
name: 'success',
|
||||||
|
id: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
const stateCommitMock = jest.fn()
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$moment: jest.fn(() => {
|
$moment: jest.fn(() => {
|
||||||
return {
|
return {
|
||||||
@ -14,6 +24,12 @@ const mocks = {
|
|||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
$apollo: {
|
||||||
|
query: apolloMock,
|
||||||
|
},
|
||||||
|
$store: {
|
||||||
|
commit: stateCommitMock,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
const propsData = {
|
const propsData = {
|
||||||
@ -39,6 +55,23 @@ describe('CreationFormular', () => {
|
|||||||
expect(wrapper.find('.component-creation-formular').exists()).toBeTruthy()
|
expect(wrapper.find('.component-creation-formular').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('server sends back moderator data', () => {
|
||||||
|
it('called store commit with mocked data', () => {
|
||||||
|
expect(stateCommitMock).toBeCalledWith('moderator', { name: 'success', id: 0 })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('server throws error for moderator data call', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
apolloMock.mockRejectedValue({ message: 'Ouch!' })
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
it('has called store commit with fake data', () => {
|
||||||
|
expect(stateCommitMock).toBeCalledWith('moderator', { id: 0, name: 'Test Moderator' })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('radio buttons to selcet month', () => {
|
describe('radio buttons to selcet month', () => {
|
||||||
it('has three radio buttons', () => {
|
it('has three radio buttons', () => {
|
||||||
expect(wrapper.findAll('input[type="radio"]').length).toBe(3)
|
expect(wrapper.findAll('input[type="radio"]').length).toBe(3)
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
? 'Einzelschöpfung für ' + item.firstName + ' ' + item.lastName + ''
|
? 'Einzelschöpfung für ' + item.firstName + ' ' + item.lastName + ''
|
||||||
: 'Mehrfachschöpfung für ' + Object.keys(this.itemsMassCreation).length + ' Mitglieder'
|
: 'Mehrfachschöpfung für ' + Object.keys(this.itemsMassCreation).length + ' Mitglieder'
|
||||||
}}
|
}}
|
||||||
{{ item }}
|
|
||||||
</h3>
|
</h3>
|
||||||
<div v-show="this.type === 'massCreation' && Object.keys(this.itemsMassCreation).length <= 0">
|
<div v-show="this.type === 'massCreation' && Object.keys(this.itemsMassCreation).length <= 0">
|
||||||
Bitte wähle ein oder Mehrere Mitglieder aus für die du Schöpfen möchtest
|
Bitte wähle ein oder Mehrere Mitglieder aus für die du Schöpfen möchtest
|
||||||
@ -24,6 +23,7 @@
|
|||||||
<b-form-radio
|
<b-form-radio
|
||||||
v-model="radioSelected"
|
v-model="radioSelected"
|
||||||
:value="beforeLastMonth"
|
:value="beforeLastMonth"
|
||||||
|
:disabled="creation[0] === 0"
|
||||||
size="lg"
|
size="lg"
|
||||||
@change="updateRadioSelected(beforeLastMonth, 0, creation[0])"
|
@change="updateRadioSelected(beforeLastMonth, 0, creation[0])"
|
||||||
>
|
>
|
||||||
@ -34,6 +34,7 @@
|
|||||||
<b-form-radio
|
<b-form-radio
|
||||||
v-model="radioSelected"
|
v-model="radioSelected"
|
||||||
:value="lastMonth"
|
:value="lastMonth"
|
||||||
|
:disabled="creation[1] === 0"
|
||||||
size="lg"
|
size="lg"
|
||||||
@change="updateRadioSelected(lastMonth, 1, creation[1])"
|
@change="updateRadioSelected(lastMonth, 1, creation[1])"
|
||||||
>
|
>
|
||||||
@ -44,6 +45,7 @@
|
|||||||
<b-form-radio
|
<b-form-radio
|
||||||
v-model="radioSelected"
|
v-model="radioSelected"
|
||||||
:value="currentMonth"
|
:value="currentMonth"
|
||||||
|
:disabled="creation[2] === 0"
|
||||||
size="lg"
|
size="lg"
|
||||||
@change="updateRadioSelected(currentMonth, 2, creation[2])"
|
@change="updateRadioSelected(currentMonth, 2, creation[2])"
|
||||||
>
|
>
|
||||||
@ -52,30 +54,29 @@
|
|||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
|
|
||||||
<b-row class="m-4">
|
<b-row class="m-4" v-show="createdIndex">
|
||||||
<label>Betrag Auswählen</label>
|
<label>Betrag Auswählen</label>
|
||||||
<b-input-group>
|
<div>
|
||||||
<template #append>
|
<b-input-group prepend="GDD" append=".00">
|
||||||
<b-input-group-text><strong class="text-danger">GDD</strong></b-input-group-text>
|
<b-form-input
|
||||||
</template>
|
type="number"
|
||||||
<b-form-input
|
v-model="value"
|
||||||
type="number"
|
:min="rangeMin"
|
||||||
v-model="value"
|
:max="rangeMax"
|
||||||
:min="rangeMin"
|
></b-form-input>
|
||||||
:max="rangeMax"
|
</b-input-group>
|
||||||
></b-form-input>
|
|
||||||
</b-input-group>
|
|
||||||
|
|
||||||
<b-input
|
<b-input-group prepend="0" :append="String(rangeMax)" class="mt-3">
|
||||||
id="range-2"
|
<b-form-input
|
||||||
class="mt-2"
|
type="range"
|
||||||
v-model="value"
|
v-model="value"
|
||||||
type="range"
|
:min="rangeMin"
|
||||||
:min="rangeMin"
|
:max="rangeMax"
|
||||||
:max="rangeMax"
|
step="10"
|
||||||
step="10"
|
@load="checkFormForUpdate('range')"
|
||||||
@load="checkFormForUpdate('range')"
|
></b-form-input>
|
||||||
></b-input>
|
</b-input-group>
|
||||||
|
</div>
|
||||||
</b-row>
|
</b-row>
|
||||||
<b-row class="m-4">
|
<b-row class="m-4">
|
||||||
<label>Text eintragen</label>
|
<label>Text eintragen</label>
|
||||||
@ -125,6 +126,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import { verifyLogin } from '../graphql/verifyLogin'
|
||||||
|
import { createPendingCreation } from '../graphql/createPendingCreation'
|
||||||
export default {
|
export default {
|
||||||
name: 'CreationFormular',
|
name: 'CreationFormular',
|
||||||
props: {
|
props: {
|
||||||
@ -163,23 +166,25 @@ export default {
|
|||||||
rangeMax: 1000,
|
rangeMax: 1000,
|
||||||
currentMonth: {
|
currentMonth: {
|
||||||
short: this.$moment().format('MMMM'),
|
short: this.$moment().format('MMMM'),
|
||||||
long: this.$moment().format('DD/MM/YYYY'),
|
long: this.$moment().format('YYYY-MM-DD'),
|
||||||
},
|
},
|
||||||
lastMonth: {
|
lastMonth: {
|
||||||
short: this.$moment().subtract(1, 'month').format('MMMM'),
|
short: this.$moment().subtract(1, 'month').format('MMMM'),
|
||||||
long: this.$moment().subtract(1, 'month').format('DD/MM/YYYY'),
|
long: this.$moment().subtract(1, 'month').format('YYYY-MM') + '-01',
|
||||||
},
|
},
|
||||||
beforeLastMonth: {
|
beforeLastMonth: {
|
||||||
short: this.$moment().subtract(2, 'month').format('MMMM'),
|
short: this.$moment().subtract(2, 'month').format('MMMM'),
|
||||||
long: this.$moment().subtract(2, 'month').format('DD/MM/YYYY'),
|
long: this.$moment().subtract(2, 'month').format('YYYY-MM') + '-01',
|
||||||
},
|
},
|
||||||
submitObj: null,
|
submitObj: null,
|
||||||
isdisabled: true,
|
isdisabled: true,
|
||||||
|
createdIndex: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// Auswählen eines Zeitraumes
|
// Auswählen eines Zeitraumes
|
||||||
updateRadioSelected(name, index, openCreation) {
|
updateRadioSelected(name, index, openCreation) {
|
||||||
|
this.createdIndex = index
|
||||||
// Wenn Mehrfachschöpfung
|
// Wenn Mehrfachschöpfung
|
||||||
if (this.type === 'massCreation') {
|
if (this.type === 'massCreation') {
|
||||||
// An Creation.vue emitten und radioSelectedMass aktualisieren
|
// An Creation.vue emitten und radioSelectedMass aktualisieren
|
||||||
@ -230,10 +235,11 @@ export default {
|
|||||||
this.submitObj = [
|
this.submitObj = [
|
||||||
{
|
{
|
||||||
item: this.itemsMassCreation,
|
item: this.itemsMassCreation,
|
||||||
datum: this.radioSelected,
|
email: this.item.email,
|
||||||
|
creationDate: this.radioSelected.long,
|
||||||
amount: this.value,
|
amount: this.value,
|
||||||
text: this.text,
|
memo: this.text,
|
||||||
moderator: this.$store.state.moderator,
|
moderator: this.$store.state.moderator.id,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
alert('MehrfachSCHÖPFUNG ABSENDEN FÜR >> ' + i + ' Mitglieder')
|
alert('MehrfachSCHÖPFUNG ABSENDEN FÜR >> ' + i + ' Mitglieder')
|
||||||
@ -246,18 +252,13 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.type === 'singleCreation') {
|
if (this.type === 'singleCreation') {
|
||||||
// hinweis das eine einzelne schöpfung ausgeführt wird an (Vorname)
|
this.submitObj = {
|
||||||
alert('SUBMIT CREATION => ' + this.type + ' >> für ' + this.item.firstName + '')
|
email: this.item.email,
|
||||||
// erstellen eines Arrays (submitObj) mit allen Daten
|
creationDate: this.radioSelected.long,
|
||||||
this.submitObj = [
|
amount: Number(this.value),
|
||||||
{
|
memo: this.text,
|
||||||
item: this.item,
|
moderator: Number(this.$store.state.moderator.id),
|
||||||
datum: this.radioSelected.long,
|
}
|
||||||
amount: this.value,
|
|
||||||
text: this.text,
|
|
||||||
moderator: this.$store.state.moderator,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
if (this.pagetype === 'PageCreationConfirm') {
|
if (this.pagetype === 'PageCreationConfirm') {
|
||||||
// hinweis das eine ein einzelne Schöpfung abgesendet wird an (email)
|
// hinweis das eine ein einzelne Schöpfung abgesendet wird an (email)
|
||||||
@ -269,22 +270,48 @@ export default {
|
|||||||
text: this.text,
|
text: this.text,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
// hinweis das eine ein einzelne Schöpfung abgesendet wird an (email)
|
this.$apollo
|
||||||
alert('EINZEL SCHÖPFUNG ABSENDEN FÜR >> ' + this.item.firstName + '')
|
.mutate({
|
||||||
// $store - offene Schöpfungen hochzählen
|
mutation: createPendingCreation,
|
||||||
this.$store.commit('openCreationsPlus', 1)
|
variables: this.submitObj,
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
this.$emit('update-user-data', this.item, result.data.createPendingCreation)
|
||||||
|
this.$toasted.success(
|
||||||
|
`Offene schöpfung (${this.value} GDD) für ${this.item.email} wurde gespeichert, liegen zur bestätigung bereit`,
|
||||||
|
)
|
||||||
|
this.$store.commit('openCreationsPlus', 1)
|
||||||
|
this.submitObj = null
|
||||||
|
this.createdIndex = null
|
||||||
|
// das creation Formular reseten
|
||||||
|
this.$refs.creationForm.reset()
|
||||||
|
// Den geschöpften Wert auf o setzen
|
||||||
|
this.value = 0
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.$toasted.error(error.message)
|
||||||
|
this.submitObj = null
|
||||||
|
// das creation Formular reseten
|
||||||
|
this.$refs.creationForm.reset()
|
||||||
|
// Den geschöpften Wert auf o setzen
|
||||||
|
this.value = 0
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// das absendeergebniss im string ansehen
|
|
||||||
alert(JSON.stringify(this.submitObj))
|
|
||||||
// das submitObj zurücksetzen
|
|
||||||
this.submitObj = null
|
|
||||||
// das creation Formular reseten
|
|
||||||
this.$refs.creationForm.reset()
|
|
||||||
// Den geschöpften Wert auf o setzen
|
|
||||||
this.value = 0
|
|
||||||
},
|
},
|
||||||
|
searchModeratorData() {
|
||||||
|
this.$apollo
|
||||||
|
.query({ query: verifyLogin })
|
||||||
|
.then((result) => {
|
||||||
|
this.$store.commit('moderator', result.data.verifyLogin)
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
this.$store.commit('moderator', { id: 0, name: 'Test Moderator' })
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.searchModeratorData()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -3,11 +3,19 @@ import NavBar from './NavBar.vue'
|
|||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
|
|
||||||
|
const storeDispatchMock = jest.fn()
|
||||||
|
const routerPushMock = jest.fn()
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$store: {
|
$store: {
|
||||||
state: {
|
state: {
|
||||||
openCreations: 1,
|
openCreations: 1,
|
||||||
|
token: 'valid-token',
|
||||||
},
|
},
|
||||||
|
dispatch: storeDispatchMock,
|
||||||
|
},
|
||||||
|
$router: {
|
||||||
|
push: routerPushMock,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,4 +35,34 @@ describe('NavBar', () => {
|
|||||||
expect(wrapper.find('.component-nabvar').exists()).toBeTruthy()
|
expect(wrapper.find('.component-nabvar').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('wallet', () => {
|
||||||
|
const assignLocationSpy = jest.fn()
|
||||||
|
beforeEach(async () => {
|
||||||
|
await wrapper.findAll('a').at(5).trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it.skip('changes widnow location to wallet', () => {
|
||||||
|
expect(assignLocationSpy).toBeCalledWith('valid-token')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('dispatches logout to store', () => {
|
||||||
|
expect(storeDispatchMock).toBeCalledWith('logout')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('logout', () => {
|
||||||
|
// const assignLocationSpy = jest.fn()
|
||||||
|
beforeEach(async () => {
|
||||||
|
await wrapper.findAll('a').at(6).trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to /logout', () => {
|
||||||
|
expect(routerPushMock).toBeCalledWith('/logout')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('dispatches logout to store', () => {
|
||||||
|
expect(storeDispatchMock).toBeCalledWith('logout')
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,12 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="component-nabvar">
|
<div class="component-nabvar">
|
||||||
<b-navbar toggleable="sm" type="dark" variant="success">
|
<b-navbar toggleable="sm" type="dark" variant="success">
|
||||||
<b-navbar-brand to="/">Adminbereich</b-navbar-brand>
|
<b-navbar-brand to="/">
|
||||||
|
<img src="img/brand/green.png" class="navbar-brand-img" alt="..." />
|
||||||
|
</b-navbar-brand>
|
||||||
|
|
||||||
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
|
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
|
||||||
|
|
||||||
<b-collapse id="nav-collapse" is-nav>
|
<b-collapse id="nav-collapse" is-nav>
|
||||||
<b-navbar-nav>
|
<b-navbar-nav>
|
||||||
|
<b-nav-item to="/">Übersicht |</b-nav-item>
|
||||||
<b-nav-item to="/user">Usersuche |</b-nav-item>
|
<b-nav-item to="/user">Usersuche |</b-nav-item>
|
||||||
<b-nav-item to="/creation">Mehrfachschöpfung</b-nav-item>
|
<b-nav-item to="/creation">Mehrfachschöpfung</b-nav-item>
|
||||||
<b-nav-item
|
<b-nav-item
|
||||||
@ -31,21 +34,6 @@ export default {
|
|||||||
name: 'navbar',
|
name: 'navbar',
|
||||||
methods: {
|
methods: {
|
||||||
logout() {
|
logout() {
|
||||||
// TODO
|
|
||||||
// this.$emit('logout')
|
|
||||||
/* this.$apollo
|
|
||||||
.query({
|
|
||||||
query: logout,
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
this.$store.dispatch('logout')
|
|
||||||
this.$router.push('/logout')
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.$store.dispatch('logout')
|
|
||||||
if (this.$router.currentRoute.path !== '/logout') this.$router.push('/logout')
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
this.$store.dispatch('logout')
|
this.$store.dispatch('logout')
|
||||||
this.$router.push('/logout')
|
this.$router.push('/logout')
|
||||||
},
|
},
|
||||||
@ -56,3 +44,8 @@ export default {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
.navbar-brand-img {
|
||||||
|
height: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -14,11 +14,11 @@
|
|||||||
{{ overlayText.text2 }}
|
{{ overlayText.text2 }}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<b-button size="lg" variant="danger" class="m-3" @click="overlayCancel">
|
<b-button size="md" variant="danger" class="m-3" @click="overlayCancel">
|
||||||
{{ overlayText.button_cancel }}
|
{{ overlayText.button_cancel }}
|
||||||
</b-button>
|
</b-button>
|
||||||
<b-button
|
<b-button
|
||||||
size="lg"
|
size="md"
|
||||||
variant="success"
|
variant="success"
|
||||||
class="m-3 text-right"
|
class="m-3 text-right"
|
||||||
@click="overlayOK(overlayBookmarkType, overlayItem)"
|
@click="overlayOK(overlayBookmarkType, overlayItem)"
|
||||||
@ -39,7 +39,7 @@
|
|||||||
<template #cell(edit_creation)="row">
|
<template #cell(edit_creation)="row">
|
||||||
<b-button
|
<b-button
|
||||||
variant="info"
|
variant="info"
|
||||||
size="lg"
|
size="md"
|
||||||
@click="editCreationUserTable(row, row.item)"
|
@click="editCreationUserTable(row, row.item)"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
@ -49,7 +49,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #cell(show_details)="row">
|
<template #cell(show_details)="row">
|
||||||
<b-button variant="info" size="lg" @click="row.toggleDetails" class="mr-2">
|
<b-button variant="info" size="md" @click="row.toggleDetails" class="mr-2">
|
||||||
<b-icon v-if="row.detailsShowing" icon="eye-slash-fill" aria-label="Help"></b-icon>
|
<b-icon v-if="row.detailsShowing" icon="eye-slash-fill" aria-label="Help"></b-icon>
|
||||||
<b-icon v-else icon="eye-fill" aria-label="Help"></b-icon>
|
<b-icon v-else icon="eye-fill" aria-label="Help"></b-icon>
|
||||||
</b-button>
|
</b-button>
|
||||||
@ -68,6 +68,7 @@
|
|||||||
:item="row.item"
|
:item="row.item"
|
||||||
:creationUserData="creationData"
|
:creationUserData="creationData"
|
||||||
@update-creation-data="updateCreationData"
|
@update-creation-data="updateCreationData"
|
||||||
|
@update-user-data="updateUserData"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<b-button size="sm" @click="row.toggleDetails">
|
<b-button size="sm" @click="row.toggleDetails">
|
||||||
@ -93,7 +94,7 @@
|
|||||||
<b-button
|
<b-button
|
||||||
variant="danger"
|
variant="danger"
|
||||||
v-show="type === 'UserListMassCreation' || type === 'PageCreationConfirm'"
|
v-show="type === 'UserListMassCreation' || type === 'PageCreationConfirm'"
|
||||||
size="lg"
|
size="md"
|
||||||
@click="overlayShow('remove', row.item)"
|
@click="overlayShow('remove', row.item)"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
@ -105,7 +106,7 @@
|
|||||||
<b-button
|
<b-button
|
||||||
variant="success"
|
variant="success"
|
||||||
v-show="type === 'PageCreationConfirm'"
|
v-show="type === 'PageCreationConfirm'"
|
||||||
size="lg"
|
size="md"
|
||||||
@click="overlayShow('confirm', row.item)"
|
@click="overlayShow('confirm', row.item)"
|
||||||
class="mr-2"
|
class="mr-2"
|
||||||
>
|
>
|
||||||
@ -232,6 +233,9 @@ export default {
|
|||||||
...data,
|
...data,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
updateUserData(rowItem, newCreation) {
|
||||||
|
rowItem.creation = newCreation
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
19
admin/src/graphql/createPendingCreation.js
Normal file
19
admin/src/graphql/createPendingCreation.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
|
export const createPendingCreation = gql`
|
||||||
|
mutation (
|
||||||
|
$email: String!
|
||||||
|
$amount: Int!
|
||||||
|
$memo: String!
|
||||||
|
$creationDate: String!
|
||||||
|
$moderator: Int!
|
||||||
|
) {
|
||||||
|
createPendingCreation(
|
||||||
|
email: $email
|
||||||
|
amount: $amount
|
||||||
|
memo: $memo
|
||||||
|
creationDate: $creationDate
|
||||||
|
moderator: $moderator
|
||||||
|
)
|
||||||
|
}
|
||||||
|
`
|
||||||
7
admin/src/graphql/getCountPendingCreations.js
Normal file
7
admin/src/graphql/getCountPendingCreations.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
|
export const countPendingCreations = gql`
|
||||||
|
query {
|
||||||
|
countPendingCreations
|
||||||
|
}
|
||||||
|
`
|
||||||
16
admin/src/graphql/getPendingCreations.js
Normal file
16
admin/src/graphql/getPendingCreations.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
|
export const getPendingCreations = gql`
|
||||||
|
query {
|
||||||
|
getPendingCreations {
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
email
|
||||||
|
amount
|
||||||
|
memo
|
||||||
|
date
|
||||||
|
moderator
|
||||||
|
creation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
12
admin/src/graphql/verifyLogin.js
Normal file
12
admin/src/graphql/verifyLogin.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
|
export const verifyLogin = gql`
|
||||||
|
query {
|
||||||
|
verifyLogin {
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
isAdmin
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
@ -21,6 +21,7 @@ import 'bootstrap/dist/css/bootstrap.css'
|
|||||||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||||
|
|
||||||
import moment from 'vue-moment'
|
import moment from 'vue-moment'
|
||||||
|
import Toasted from 'vue-toasted'
|
||||||
|
|
||||||
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
|
const httpLink = new HttpLink({ uri: CONFIG.GRAPHQL_URI })
|
||||||
|
|
||||||
@ -32,18 +33,17 @@ const authLink = new ApolloLink((operation, forward) => {
|
|||||||
Authorization: token && token.length > 0 ? `Bearer ${token}` : '',
|
Authorization: token && token.length > 0 ? `Bearer ${token}` : '',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
return forward(operation)
|
return forward(operation).map((response) => {
|
||||||
/* .map((response) => {
|
|
||||||
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
|
if (response.errors && response.errors[0].message === '403.13 - Client certificate revoked') {
|
||||||
response.errors[0].message = i18n.t('error.session-expired')
|
response.errors[0].message = i18n.t('error.session-expired')
|
||||||
store.dispatch('logout', null)
|
store.dispatch('logout', null)
|
||||||
if (router.currentRoute.path !== '/login') router.push('/login')
|
if (router.currentRoute.path !== '/logout') router.push('/logout')
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
const newToken = operation.getContext().response.headers.get('token')
|
const newToken = operation.getContext().response.headers.get('token')
|
||||||
if (newToken) store.commit('token', newToken)
|
if (newToken) store.commit('token', newToken)
|
||||||
return response
|
return response
|
||||||
}) */
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const apolloClient = new ApolloClient({
|
const apolloClient = new ApolloClient({
|
||||||
@ -63,7 +63,19 @@ Vue.use(moment)
|
|||||||
|
|
||||||
Vue.use(VueApollo)
|
Vue.use(VueApollo)
|
||||||
|
|
||||||
addNavigationGuards(router, store)
|
Vue.use(Toasted, {
|
||||||
|
position: 'top-center',
|
||||||
|
duration: 5000,
|
||||||
|
fullWidth: true,
|
||||||
|
action: {
|
||||||
|
text: 'x',
|
||||||
|
onClick: (e, toastObject) => {
|
||||||
|
toastObject.goAway(0)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
addNavigationGuards(router, store, apolloProvider.defaultClient)
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
moment,
|
moment,
|
||||||
|
|||||||
@ -3,12 +3,14 @@ import './main'
|
|||||||
import CONFIG from './config'
|
import CONFIG from './config'
|
||||||
|
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
import VueApollo from 'vue-apollo'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import VueI18n from 'vue-i18n'
|
import VueI18n from 'vue-i18n'
|
||||||
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
|
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
|
||||||
import moment from 'vue-moment'
|
import moment from 'vue-moment'
|
||||||
|
|
||||||
jest.mock('vue')
|
jest.mock('vue')
|
||||||
|
jest.mock('vue-apollo')
|
||||||
jest.mock('vuex')
|
jest.mock('vuex')
|
||||||
jest.mock('vue-i18n')
|
jest.mock('vue-i18n')
|
||||||
jest.mock('vue-moment')
|
jest.mock('vue-moment')
|
||||||
@ -55,6 +57,10 @@ describe('main', () => {
|
|||||||
expect(InMemoryCache).toBeCalled()
|
expect(InMemoryCache).toBeCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('calls the VueApollo', () => {
|
||||||
|
expect(VueApollo).toBeCalled()
|
||||||
|
})
|
||||||
|
|
||||||
it('calls Vue', () => {
|
it('calls Vue', () => {
|
||||||
expect(Vue).toBeCalled()
|
expect(Vue).toBeCalled()
|
||||||
})
|
})
|
||||||
@ -63,16 +69,16 @@ describe('main', () => {
|
|||||||
expect(VueI18n).toBeCalled()
|
expect(VueI18n).toBeCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it.skip('calls BootstrapVue', () => {
|
it('calls BootstrapVue', () => {
|
||||||
expect(BootstrapVue).toBeCalled()
|
expect(Vue.use).toBeCalledWith(BootstrapVue)
|
||||||
})
|
})
|
||||||
|
|
||||||
it.skip('calls IconsPlugin', () => {
|
it('calls IconsPlugin', () => {
|
||||||
expect(IconsPlugin).toBeCalled()
|
expect(Vue.use).toBeCalledWith(IconsPlugin)
|
||||||
})
|
})
|
||||||
|
|
||||||
it.skip('calls Moment', () => {
|
it('calls Moment', () => {
|
||||||
expect(moment).toBeCalled()
|
expect(Vue.use).toBeCalledWith(moment)
|
||||||
})
|
})
|
||||||
|
|
||||||
it.skip('creates a store', () => {
|
it.skip('creates a store', () => {
|
||||||
|
|||||||
@ -4,11 +4,47 @@ import CreationConfirm from './CreationConfirm.vue'
|
|||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
|
|
||||||
const storeCommitMock = jest.fn()
|
const storeCommitMock = jest.fn()
|
||||||
|
const toastedErrorMock = jest.fn()
|
||||||
|
const apolloQueryMock = jest.fn().mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
getPendingCreations: [
|
||||||
|
{
|
||||||
|
firstName: 'Bibi',
|
||||||
|
lastName: 'Bloxberg',
|
||||||
|
email: 'bibi@bloxberg.de',
|
||||||
|
amount: 500,
|
||||||
|
memo: 'Danke für alles',
|
||||||
|
date: new Date(),
|
||||||
|
moderator: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
firstName: 'Räuber',
|
||||||
|
lastName: 'Hotzenplotz',
|
||||||
|
email: 'raeuber@hotzenplotz.de',
|
||||||
|
amount: 1000000,
|
||||||
|
memo: 'Gut Ergatert',
|
||||||
|
date: new Date(),
|
||||||
|
moderator: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$store: {
|
$store: {
|
||||||
commit: storeCommitMock,
|
commit: storeCommitMock,
|
||||||
},
|
},
|
||||||
|
$apollo: {
|
||||||
|
query: apolloQueryMock,
|
||||||
|
},
|
||||||
|
$toasted: {
|
||||||
|
error: toastedErrorMock,
|
||||||
|
},
|
||||||
|
$moment: jest.fn((value) => {
|
||||||
|
return {
|
||||||
|
format: jest.fn((format) => value),
|
||||||
|
}
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('CreationConfirm', () => {
|
describe('CreationConfirm', () => {
|
||||||
@ -32,9 +68,22 @@ describe('CreationConfirm', () => {
|
|||||||
it('commits resetOpenCreations to store', () => {
|
it('commits resetOpenCreations to store', () => {
|
||||||
expect(storeCommitMock).toBeCalledWith('resetOpenCreations')
|
expect(storeCommitMock).toBeCalledWith('resetOpenCreations')
|
||||||
})
|
})
|
||||||
|
it('commits setOpenCreations to store', () => {
|
||||||
|
expect(storeCommitMock).toBeCalledWith('setOpenCreations', 2)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
it('commits openCreationsPlus to store', () => {
|
describe('server response is error', () => {
|
||||||
expect(storeCommitMock).toBeCalledWith('openCreationsPlus', 5)
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
apolloQueryMock.mockRejectedValue({
|
||||||
|
message: 'Ouch!',
|
||||||
|
})
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toast an error message', () => {
|
||||||
|
expect(toastedErrorMock).toBeCalledWith('Ouch!')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="creation-confirm">
|
<div class="creation-confirm">
|
||||||
<small class="bg-danger text-light p-1">
|
|
||||||
Die anzahl der offene Schöpfungen stimmen nicht! Diese wird bei absenden im $store
|
|
||||||
hochgezählt. Die Liste die hier angezeigt wird ist SIMULIERT!
|
|
||||||
</small>
|
|
||||||
<user-table
|
<user-table
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
type="PageCreationConfirm"
|
type="PageCreationConfirm"
|
||||||
@ -15,6 +11,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import UserTable from '../components/UserTable.vue'
|
import UserTable from '../components/UserTable.vue'
|
||||||
|
import { getPendingCreations } from '../graphql/getPendingCreations'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CreationConfirm',
|
name: 'CreationConfirm',
|
||||||
@ -30,98 +27,25 @@ export default {
|
|||||||
{ key: 'firstName', label: 'Vorname' },
|
{ key: 'firstName', label: 'Vorname' },
|
||||||
{ key: 'lastName', label: 'Nachname' },
|
{ key: 'lastName', label: 'Nachname' },
|
||||||
{
|
{
|
||||||
key: 'creation_gdd',
|
key: 'amount',
|
||||||
label: 'Schöpfung',
|
label: 'Schöpfung',
|
||||||
formatter: (value) => {
|
formatter: (value) => {
|
||||||
return value + ' GDD'
|
return value + ' GDD'
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ key: 'text', label: 'Text' },
|
{ key: 'memo', label: 'Text' },
|
||||||
{
|
{
|
||||||
key: 'creation_date',
|
key: 'date',
|
||||||
label: 'Datum',
|
label: 'Datum',
|
||||||
formatter: (value) => {
|
formatter: (value) => {
|
||||||
return value.long
|
return this.$moment(value).format('ll')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ key: 'creation_moderator', label: 'Moderator' },
|
{ key: 'moderator', label: 'Moderator' },
|
||||||
{ key: 'edit_creation', label: 'ändern' },
|
{ key: 'edit_creation', label: 'ändern' },
|
||||||
{ key: 'confirm', label: 'speichern' },
|
{ key: 'confirm', label: 'speichern' },
|
||||||
],
|
],
|
||||||
confirmResult: [
|
confirmResult: [],
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
email: 'dickerson@web.de',
|
|
||||||
firstName: 'Dickerson',
|
|
||||||
lastName: 'Macdonald',
|
|
||||||
creation: '[450,200,700]',
|
|
||||||
creation_gdd: '1000',
|
|
||||||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam ',
|
|
||||||
|
|
||||||
creation_date: {
|
|
||||||
short: 'November',
|
|
||||||
long: '22/11/2021',
|
|
||||||
},
|
|
||||||
creation_moderator: 'Manuela Gast',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
email: 'larsen@woob.de',
|
|
||||||
firstName: 'Larsen',
|
|
||||||
lastName: 'Shaw',
|
|
||||||
creation: '[300,200,1000]',
|
|
||||||
creation_gdd: '1000',
|
|
||||||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam ',
|
|
||||||
|
|
||||||
creation_date: {
|
|
||||||
short: 'November',
|
|
||||||
long: '03/11/2021',
|
|
||||||
},
|
|
||||||
creation_moderator: 'Manuela Gast',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 3,
|
|
||||||
email: 'geneva@tete.de',
|
|
||||||
firstName: 'Geneva',
|
|
||||||
lastName: 'Wilson',
|
|
||||||
creation: '[350,200,900]',
|
|
||||||
creation_gdd: '1000',
|
|
||||||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam',
|
|
||||||
creation_date: {
|
|
||||||
short: 'September',
|
|
||||||
long: '27/09/2021',
|
|
||||||
},
|
|
||||||
creation_moderator: 'Manuela Gast',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 4,
|
|
||||||
email: 'viewrter@asdfvb.com',
|
|
||||||
firstName: 'Soledare',
|
|
||||||
lastName: 'Takker',
|
|
||||||
creation: '[100,400,800]',
|
|
||||||
creation_gdd: '500',
|
|
||||||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo ',
|
|
||||||
creation_date: {
|
|
||||||
short: 'Oktober',
|
|
||||||
long: '12/10/2021',
|
|
||||||
},
|
|
||||||
creation_moderator: 'Evelyn Roller',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 5,
|
|
||||||
email: 'dickerson@web.de',
|
|
||||||
firstName: 'Dickerson',
|
|
||||||
lastName: 'Macdonald',
|
|
||||||
creation: '[100,400,800]',
|
|
||||||
creation_gdd: '200',
|
|
||||||
text: 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At',
|
|
||||||
creation_date: {
|
|
||||||
short: 'September',
|
|
||||||
long: '05/09/2021',
|
|
||||||
},
|
|
||||||
creation_moderator: 'Manuela Gast',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -140,10 +64,23 @@ export default {
|
|||||||
this.$store.commit('openCreationsMinus', 1)
|
this.$store.commit('openCreationsMinus', 1)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
getPendingCreations() {
|
||||||
|
this.$apollo
|
||||||
|
.query({
|
||||||
|
query: getPendingCreations,
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
this.$store.commit('resetOpenCreations')
|
||||||
|
this.confirmResult = result.data.getPendingCreations.reverse()
|
||||||
|
this.$store.commit('setOpenCreations', result.data.getPendingCreations.length)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.$toasted.error(error.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
},
|
},
|
||||||
created() {
|
async created() {
|
||||||
this.$store.commit('resetOpenCreations')
|
await this.getPendingCreations()
|
||||||
this.$store.commit('openCreationsPlus', Object.keys(this.confirmResult).length)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -76,7 +76,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import { getPendingCreations } from '../graphql/getPendingCreations'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'overview',
|
name: 'overview',
|
||||||
|
methods: {
|
||||||
|
getPendingCreations() {
|
||||||
|
this.$apollo
|
||||||
|
.query({
|
||||||
|
query: getPendingCreations,
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
this.$store.commit('setOpenCreations', result.data.getPendingCreations.length)
|
||||||
|
})
|
||||||
|
.catch()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getPendingCreations()
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -32,7 +32,13 @@ export default {
|
|||||||
{ key: 'email', label: 'Email' },
|
{ key: 'email', label: 'Email' },
|
||||||
{ key: 'firstName', label: 'Firstname' },
|
{ key: 'firstName', label: 'Firstname' },
|
||||||
{ key: 'lastName', label: 'Lastname' },
|
{ key: 'lastName', label: 'Lastname' },
|
||||||
{ key: 'creation', label: 'Creation' },
|
{
|
||||||
|
key: 'creation',
|
||||||
|
label: 'Creation',
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
return String(value)
|
||||||
|
},
|
||||||
|
},
|
||||||
{ key: 'show_details', label: 'Details' },
|
{ key: 'show_details', label: 'Details' },
|
||||||
],
|
],
|
||||||
searchResult: [],
|
searchResult: [],
|
||||||
|
|||||||
@ -1,12 +1,28 @@
|
|||||||
|
import { verifyLogin } from '../graphql/verifyLogin'
|
||||||
import CONFIG from '../config'
|
import CONFIG from '../config'
|
||||||
|
|
||||||
const addNavigationGuards = (router, store) => {
|
const addNavigationGuards = (router, store, apollo) => {
|
||||||
// store token on `authenticate`
|
// store token on `authenticate`
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach(async (to, from, next) => {
|
||||||
if (to.path === '/authenticate' && to.query && to.query.token) {
|
if (to.path === '/authenticate' && to.query && to.query.token) {
|
||||||
// TODO verify user to get user data
|
|
||||||
store.commit('token', to.query.token)
|
store.commit('token', to.query.token)
|
||||||
next({ path: '/' })
|
await apollo
|
||||||
|
.query({
|
||||||
|
query: verifyLogin,
|
||||||
|
fetchPolicy: 'network-only',
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
const moderator = result.data.verifyLogin
|
||||||
|
if (moderator.isAdmin) {
|
||||||
|
store.commit('moderator', moderator)
|
||||||
|
next({ path: '/' })
|
||||||
|
} else {
|
||||||
|
next({ path: '/not-found' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
next({ path: '/not-found' })
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
next()
|
next()
|
||||||
}
|
}
|
||||||
@ -16,7 +32,9 @@ const addNavigationGuards = (router, store) => {
|
|||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
if (
|
if (
|
||||||
!CONFIG.DEBUG_DISABLE_AUTH && // we did not disabled the auth module for debug purposes
|
!CONFIG.DEBUG_DISABLE_AUTH && // we did not disabled the auth module for debug purposes
|
||||||
!store.state.token && // we do not have a token
|
(!store.state.token || // we do not have a token
|
||||||
|
!store.state.moderator || // no moderator set in store
|
||||||
|
!store.state.moderator.isAdmin) && // user is no admin
|
||||||
to.path !== '/not-found' && // we are not on `not-found`
|
to.path !== '/not-found' && // we are not on `not-found`
|
||||||
to.path !== '/logout' // we are not on `logout`
|
to.path !== '/logout' // we are not on `logout`
|
||||||
) {
|
) {
|
||||||
|
|||||||
@ -2,6 +2,13 @@ import addNavigationGuards from './guards'
|
|||||||
import router from './router'
|
import router from './router'
|
||||||
|
|
||||||
const storeCommitMock = jest.fn()
|
const storeCommitMock = jest.fn()
|
||||||
|
const apolloQueryMock = jest.fn().mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
verifyLogin: {
|
||||||
|
isAdmin: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
const store = {
|
const store = {
|
||||||
commit: storeCommitMock,
|
commit: storeCommitMock,
|
||||||
@ -10,7 +17,11 @@ const store = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
addNavigationGuards(router, store)
|
const apollo = {
|
||||||
|
query: apolloQueryMock,
|
||||||
|
}
|
||||||
|
|
||||||
|
addNavigationGuards(router, store, apollo)
|
||||||
|
|
||||||
describe('navigation guards', () => {
|
describe('navigation guards', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@ -21,18 +32,70 @@ describe('navigation guards', () => {
|
|||||||
const navGuard = router.beforeHooks[0]
|
const navGuard = router.beforeHooks[0]
|
||||||
const next = jest.fn()
|
const next = jest.fn()
|
||||||
|
|
||||||
describe('with valid token', () => {
|
describe('with valid token and as admin', () => {
|
||||||
it('commits the token to the store', async () => {
|
beforeEach(() => {
|
||||||
navGuard({ path: '/authenticate', query: { token: 'valid-token' } }, {}, next)
|
navGuard({ path: '/authenticate', query: { token: 'valid-token' } }, {}, next)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('commits the token to the store', async () => {
|
||||||
expect(storeCommitMock).toBeCalledWith('token', 'valid-token')
|
expect(storeCommitMock).toBeCalledWith('token', 'valid-token')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('commits the moderator to the store', () => {
|
||||||
|
expect(storeCommitMock).toBeCalledWith('moderator', { isAdmin: true })
|
||||||
|
})
|
||||||
|
|
||||||
it('redirects to /', async () => {
|
it('redirects to /', async () => {
|
||||||
navGuard({ path: '/authenticate', query: { token: 'valid-token' } }, {}, next)
|
|
||||||
expect(next).toBeCalledWith({ path: '/' })
|
expect(next).toBeCalledWith({ path: '/' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('with valid token and not as admin', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
apolloQueryMock.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
verifyLogin: {
|
||||||
|
isAdmin: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
navGuard({ path: '/authenticate', query: { token: 'valid-token' } }, {}, next)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('commits the token to the store', async () => {
|
||||||
|
expect(storeCommitMock).toBeCalledWith('token', 'valid-token')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not commit the moderator to the store', () => {
|
||||||
|
expect(storeCommitMock).not.toBeCalledWith('moderator', { isAdmin: false })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to /not-found', async () => {
|
||||||
|
expect(next).toBeCalledWith({ path: '/not-found' })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('with valid token and server error on verification', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
apolloQueryMock.mockRejectedValue({
|
||||||
|
message: 'Ouch!',
|
||||||
|
})
|
||||||
|
navGuard({ path: '/authenticate', query: { token: 'valid-token' } }, {}, next)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('commits the token to the store', async () => {
|
||||||
|
expect(storeCommitMock).toBeCalledWith('token', 'valid-token')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not commit the moderator to the store', () => {
|
||||||
|
expect(storeCommitMock).not.toBeCalledWith('moderator', { isAdmin: false })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('redirects to /not-found', async () => {
|
||||||
|
expect(next).toBeCalledWith({ path: '/not-found' })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('without valid token', () => {
|
describe('without valid token', () => {
|
||||||
it('does not commit the token to the store', async () => {
|
it('does not commit the token to the store', async () => {
|
||||||
navGuard({ path: '/authenticate' }, {}, next)
|
navGuard({ path: '/authenticate' }, {}, next)
|
||||||
@ -55,9 +118,16 @@ describe('navigation guards', () => {
|
|||||||
expect(next).toBeCalledWith({ path: '/not-found' })
|
expect(next).toBeCalledWith({ path: '/not-found' })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('does not redirect when token in store', () => {
|
it('redirects to not found with token in store and not moderator', () => {
|
||||||
store.state.token = 'valid token'
|
store.state.token = 'valid token'
|
||||||
navGuard({ path: '/' }, {}, next)
|
navGuard({ path: '/' }, {}, next)
|
||||||
|
expect(next).toBeCalledWith({ path: '/not-found' })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not redirect with token in store and as moderator', () => {
|
||||||
|
store.state.token = 'valid token'
|
||||||
|
store.state.moderator = { isAdmin: true }
|
||||||
|
navGuard({ path: '/' }, {}, next)
|
||||||
expect(next).toBeCalledWith()
|
expect(next).toBeCalledWith()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -18,11 +18,18 @@ export const mutations = {
|
|||||||
token: (state, token) => {
|
token: (state, token) => {
|
||||||
state.token = token
|
state.token = token
|
||||||
},
|
},
|
||||||
|
setOpenCreations: (state, openCreations) => {
|
||||||
|
state.openCreations = openCreations
|
||||||
|
},
|
||||||
|
moderator: (state, moderator) => {
|
||||||
|
state.moderator = moderator
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
logout: ({ commit, state }) => {
|
logout: ({ commit, state }) => {
|
||||||
commit('token', null)
|
commit('token', null)
|
||||||
|
commit('moderator', null)
|
||||||
window.localStorage.clear()
|
window.localStorage.clear()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -35,7 +42,7 @@ const store = new Vuex.Store({
|
|||||||
],
|
],
|
||||||
state: {
|
state: {
|
||||||
token: CONFIG.DEBUG_DISABLE_AUTH ? 'validToken' : null,
|
token: CONFIG.DEBUG_DISABLE_AUTH ? 'validToken' : null,
|
||||||
moderator: 'Dertest Moderator',
|
moderator: null,
|
||||||
openCreations: 0,
|
openCreations: 0,
|
||||||
},
|
},
|
||||||
// Syncronous mutation of the state
|
// Syncronous mutation of the state
|
||||||
|
|||||||
@ -1,11 +1,19 @@
|
|||||||
import store, { mutations, actions } from './store'
|
import store, { mutations, actions } from './store'
|
||||||
|
import CONFIG from '../config'
|
||||||
|
|
||||||
const { token, openCreationsPlus, openCreationsMinus, resetOpenCreations } = mutations
|
jest.mock('../config')
|
||||||
|
|
||||||
|
const {
|
||||||
|
token,
|
||||||
|
openCreationsPlus,
|
||||||
|
openCreationsMinus,
|
||||||
|
resetOpenCreations,
|
||||||
|
setOpenCreations,
|
||||||
|
moderator,
|
||||||
|
} = mutations
|
||||||
const { logout } = actions
|
const { logout } = actions
|
||||||
|
|
||||||
const CONFIG = {
|
CONFIG.DEBUG_DISABLE_AUTH = true
|
||||||
DEBUG_DISABLE_AUTH: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('Vuex store', () => {
|
describe('Vuex store', () => {
|
||||||
describe('mutations', () => {
|
describe('mutations', () => {
|
||||||
@ -40,6 +48,22 @@ describe('Vuex store', () => {
|
|||||||
expect(state.openCreations).toEqual(0)
|
expect(state.openCreations).toEqual(0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('moderator', () => {
|
||||||
|
it('sets the moderator object in state', () => {
|
||||||
|
const state = { moderator: null }
|
||||||
|
moderator(state, { id: 1 })
|
||||||
|
expect(state.moderator).toEqual({ id: 1 })
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('setOpenCreations', () => {
|
||||||
|
it('sets the open creations to given value', () => {
|
||||||
|
const state = { openCreations: 24 }
|
||||||
|
setOpenCreations(state, 12)
|
||||||
|
expect(state.openCreations).toEqual(12)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('actions', () => {
|
describe('actions', () => {
|
||||||
@ -57,6 +81,11 @@ describe('Vuex store', () => {
|
|||||||
expect(commit).toBeCalledWith('token', null)
|
expect(commit).toBeCalledWith('token', null)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('deletes the moderator in store', () => {
|
||||||
|
logout({ commit, state })
|
||||||
|
expect(commit).toBeCalledWith('moderator', null)
|
||||||
|
})
|
||||||
|
|
||||||
it.skip('clears the window local storage', () => {
|
it.skip('clears the window local storage', () => {
|
||||||
expect(windowStorageMock).toBeCalled()
|
expect(windowStorageMock).toBeCalled()
|
||||||
})
|
})
|
||||||
|
|||||||
@ -12524,6 +12524,11 @@ vue-template-es2015-compiler@^1.6.0, vue-template-es2015-compiler@^1.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
|
||||||
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
|
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
|
||||||
|
|
||||||
|
vue-toasted@^1.1.28:
|
||||||
|
version "1.1.28"
|
||||||
|
resolved "https://registry.yarnpkg.com/vue-toasted/-/vue-toasted-1.1.28.tgz#dbabb83acc89f7a9e8765815e491d79f0dc65c26"
|
||||||
|
integrity sha512-UUzr5LX51UbbiROSGZ49GOgSzFxaMHK6L00JV8fir/CYNJCpIIvNZ5YmS4Qc8Y2+Z/4VVYRpeQL2UO0G800Raw==
|
||||||
|
|
||||||
vue@^2.6.11:
|
vue@^2.6.11:
|
||||||
version "2.6.14"
|
version "2.6.14"
|
||||||
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
|
resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.14.tgz#e51aa5250250d569a3fbad3a8a5a687d6036e235"
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
"jest": "^27.2.4",
|
"jest": "^27.2.4",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"module-alias": "^2.2.2",
|
"module-alias": "^2.2.2",
|
||||||
|
"moment": "^2.29.1",
|
||||||
"mysql2": "^2.3.0",
|
"mysql2": "^2.3.0",
|
||||||
"nodemailer": "^6.6.5",
|
"nodemailer": "^6.6.5",
|
||||||
"random-bigint": "^0.0.1",
|
"random-bigint": "^0.0.1",
|
||||||
|
|||||||
19
backend/src/graphql/arg/CreatePendingCreationArgs.ts
Normal file
19
backend/src/graphql/arg/CreatePendingCreationArgs.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { ArgsType, Field, Int } from 'type-graphql'
|
||||||
|
|
||||||
|
@ArgsType()
|
||||||
|
export default class CreatePendingCreationArgs {
|
||||||
|
@Field(() => String)
|
||||||
|
email: string
|
||||||
|
|
||||||
|
@Field(() => Int)
|
||||||
|
amount: number
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
memo: string
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
creationDate: string
|
||||||
|
|
||||||
|
@Field(() => Int)
|
||||||
|
moderator: number
|
||||||
|
}
|
||||||
0
backend/src/graphql/model/CreatePendingCreation.ts
Normal file
0
backend/src/graphql/model/CreatePendingCreation.ts
Normal file
34
backend/src/graphql/model/PendingCreation.ts
Normal file
34
backend/src/graphql/model/PendingCreation.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { ObjectType, Field, Int } from 'type-graphql'
|
||||||
|
|
||||||
|
@ObjectType()
|
||||||
|
export class PendingCreation {
|
||||||
|
@Field(() => String)
|
||||||
|
firstName: string
|
||||||
|
|
||||||
|
@Field(() => Int)
|
||||||
|
id?: number
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
lastName: string
|
||||||
|
|
||||||
|
@Field(() => Number)
|
||||||
|
userId: number
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
email: string
|
||||||
|
|
||||||
|
@Field(() => Date)
|
||||||
|
date: Date
|
||||||
|
|
||||||
|
@Field(() => String)
|
||||||
|
memo: string
|
||||||
|
|
||||||
|
@Field(() => Number)
|
||||||
|
amount: BigInt
|
||||||
|
|
||||||
|
@Field(() => Number)
|
||||||
|
moderator: number
|
||||||
|
|
||||||
|
@Field(() => [Number])
|
||||||
|
creation: number[]
|
||||||
|
}
|
||||||
@ -12,6 +12,7 @@ export class User {
|
|||||||
*/
|
*/
|
||||||
constructor(json?: any) {
|
constructor(json?: any) {
|
||||||
if (json) {
|
if (json) {
|
||||||
|
this.id = json.id
|
||||||
this.email = json.email
|
this.email = json.email
|
||||||
this.firstName = json.first_name
|
this.firstName = json.first_name
|
||||||
this.lastName = json.last_name
|
this.lastName = json.last_name
|
||||||
@ -24,6 +25,9 @@ export class User {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Field(() => Number)
|
||||||
|
id: number
|
||||||
|
|
||||||
@Field(() => String)
|
@Field(() => String)
|
||||||
email: string
|
email: string
|
||||||
|
|
||||||
|
|||||||
@ -1,28 +1,200 @@
|
|||||||
import { Resolver, Query, Arg, Authorized } from 'type-graphql'
|
import { Resolver, Query, Arg, Args, Authorized, Mutation } from 'type-graphql'
|
||||||
import { getCustomRepository } from 'typeorm'
|
import { getCustomRepository, Raw } from 'typeorm'
|
||||||
import { UserAdmin } from '../model/UserAdmin'
|
import { UserAdmin } from '../model/UserAdmin'
|
||||||
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
|
import { PendingCreation } from '../model/PendingCreation'
|
||||||
import { RIGHTS } from '../../auth/RIGHTS'
|
import { RIGHTS } from '../../auth/RIGHTS'
|
||||||
|
import { TransactionCreationRepository } from '../../typeorm/repository/TransactionCreation'
|
||||||
|
import { PendingCreationRepository } from '../../typeorm/repository/PendingCreation'
|
||||||
|
import { UserRepository } from '../../typeorm/repository/User'
|
||||||
|
import CreatePendingCreationArgs from '../arg/CreatePendingCreationArgs'
|
||||||
|
import moment from 'moment'
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class AdminResolver {
|
export class AdminResolver {
|
||||||
@Authorized([RIGHTS.SEARCH_USERS])
|
@Authorized([RIGHTS.SEARCH_USERS])
|
||||||
@Query(() => [UserAdmin])
|
@Query(() => [UserAdmin])
|
||||||
async searchUsers(@Arg('searchText') searchText: string): Promise<UserAdmin[]> {
|
async searchUsers(@Arg('searchText') searchText: string): Promise<UserAdmin[]> {
|
||||||
const loginUserRepository = getCustomRepository(LoginUserRepository)
|
const userRepository = getCustomRepository(UserRepository)
|
||||||
const loginUsers = await loginUserRepository.findBySearchCriteria(searchText)
|
const users = await userRepository.findBySearchCriteria(searchText)
|
||||||
const users = loginUsers.map((loginUser) => {
|
const adminUsers = await Promise.all(
|
||||||
const user = new UserAdmin()
|
users.map(async (user) => {
|
||||||
user.firstName = loginUser.firstName
|
const adminUser = new UserAdmin()
|
||||||
user.lastName = loginUser.lastName
|
adminUser.firstName = user.firstName
|
||||||
user.email = loginUser.email
|
adminUser.lastName = user.lastName
|
||||||
user.creation = [
|
adminUser.email = user.email
|
||||||
(Math.floor(Math.random() * 50) + 1) * 20,
|
adminUser.creation = await getUserCreations(user.id)
|
||||||
(Math.floor(Math.random() * 50) + 1) * 20,
|
return adminUser
|
||||||
(Math.floor(Math.random() * 50) + 1) * 20,
|
}),
|
||||||
]
|
)
|
||||||
return user
|
return adminUsers
|
||||||
})
|
}
|
||||||
return users
|
|
||||||
|
@Mutation(() => [Number])
|
||||||
|
async createPendingCreation(
|
||||||
|
@Args() { email, amount, memo, creationDate, moderator }: CreatePendingCreationArgs,
|
||||||
|
): Promise<number[]> {
|
||||||
|
const userRepository = getCustomRepository(UserRepository)
|
||||||
|
const user = await userRepository.findByEmail(email)
|
||||||
|
|
||||||
|
const creations = await getUserCreations(user.id)
|
||||||
|
const creationDateObj = new Date(creationDate)
|
||||||
|
if (isCreationValid(creations, amount, creationDateObj)) {
|
||||||
|
const pendingCreationRepository = getCustomRepository(PendingCreationRepository)
|
||||||
|
const loginPendingTaskAdmin = pendingCreationRepository.create()
|
||||||
|
loginPendingTaskAdmin.userId = user.id
|
||||||
|
loginPendingTaskAdmin.amount = BigInt(amount * 10000)
|
||||||
|
loginPendingTaskAdmin.created = new Date()
|
||||||
|
loginPendingTaskAdmin.date = creationDateObj
|
||||||
|
loginPendingTaskAdmin.memo = memo
|
||||||
|
loginPendingTaskAdmin.moderator = moderator
|
||||||
|
|
||||||
|
pendingCreationRepository.save(loginPendingTaskAdmin)
|
||||||
|
}
|
||||||
|
return await getUserCreations(user.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Query(() => [PendingCreation])
|
||||||
|
async getPendingCreations(): Promise<PendingCreation[]> {
|
||||||
|
const pendingCreationRepository = getCustomRepository(PendingCreationRepository)
|
||||||
|
const pendingCreations = await pendingCreationRepository.find()
|
||||||
|
|
||||||
|
const pendingCreationsPromise = await Promise.all(
|
||||||
|
pendingCreations.map(async (pendingCreation) => {
|
||||||
|
const userRepository = getCustomRepository(UserRepository)
|
||||||
|
const user = await userRepository.findOneOrFail({ id: pendingCreation.userId })
|
||||||
|
|
||||||
|
const newPendingCreation = {
|
||||||
|
...pendingCreation,
|
||||||
|
firstName: user.firstName,
|
||||||
|
lastName: user.lastName,
|
||||||
|
email: user.email,
|
||||||
|
creation: await getUserCreations(user.id),
|
||||||
|
}
|
||||||
|
|
||||||
|
return newPendingCreation
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
return pendingCreationsPromise
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getUserCreations(id: number): Promise<number[]> {
|
||||||
|
const dateNextMonth = moment().add(1, 'month').format('YYYY-MM') + '-01'
|
||||||
|
const dateMonth = moment().format('YYYY-MM') + '-01'
|
||||||
|
const dateLastMonth = moment().subtract(1, 'month').format('YYYY-MM') + '-01'
|
||||||
|
const dateBeforeLastMonth = moment().subtract(2, 'month').format('YYYY-MM') + '-01'
|
||||||
|
|
||||||
|
const transactionCreationRepository = getCustomRepository(TransactionCreationRepository)
|
||||||
|
const createdAmountBeforeLastMonth = await transactionCreationRepository
|
||||||
|
.createQueryBuilder('transaction_creations')
|
||||||
|
.select('SUM(transaction_creations.amount)', 'sum')
|
||||||
|
.where('transaction_creations.state_user_id = :id', { id })
|
||||||
|
.andWhere({
|
||||||
|
targetDate: Raw((alias) => `${alias} >= :date and ${alias} < :enddate`, {
|
||||||
|
date: dateBeforeLastMonth,
|
||||||
|
enddate: dateLastMonth,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.getRawOne()
|
||||||
|
|
||||||
|
const createdAmountLastMonth = await transactionCreationRepository
|
||||||
|
.createQueryBuilder('transaction_creations')
|
||||||
|
.select('SUM(transaction_creations.amount)', 'sum')
|
||||||
|
.where('transaction_creations.state_user_id = :id', { id })
|
||||||
|
.andWhere({
|
||||||
|
targetDate: Raw((alias) => `${alias} >= :date and ${alias} < :enddate`, {
|
||||||
|
date: dateLastMonth,
|
||||||
|
enddate: dateMonth,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.getRawOne()
|
||||||
|
|
||||||
|
const createdAmountMonth = await transactionCreationRepository
|
||||||
|
.createQueryBuilder('transaction_creations')
|
||||||
|
.select('SUM(transaction_creations.amount)', 'sum')
|
||||||
|
.where('transaction_creations.state_user_id = :id', { id })
|
||||||
|
.andWhere({
|
||||||
|
targetDate: Raw((alias) => `${alias} >= :date and ${alias} < :enddate`, {
|
||||||
|
date: dateMonth,
|
||||||
|
enddate: dateNextMonth,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.getRawOne()
|
||||||
|
|
||||||
|
const pendingCreationRepository = getCustomRepository(PendingCreationRepository)
|
||||||
|
const pendingAmountMounth = await pendingCreationRepository
|
||||||
|
.createQueryBuilder('login_pending_tasks_admin')
|
||||||
|
.select('SUM(login_pending_tasks_admin.amount)', 'sum')
|
||||||
|
.where('login_pending_tasks_admin.userId = :id', { id })
|
||||||
|
.andWhere({
|
||||||
|
date: Raw((alias) => `${alias} >= :date and ${alias} < :enddate`, {
|
||||||
|
date: dateMonth,
|
||||||
|
enddate: dateNextMonth,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.getRawOne()
|
||||||
|
|
||||||
|
const pendingAmountLastMounth = await pendingCreationRepository
|
||||||
|
.createQueryBuilder('login_pending_tasks_admin')
|
||||||
|
.select('SUM(login_pending_tasks_admin.amount)', 'sum')
|
||||||
|
.where('login_pending_tasks_admin.userId = :id', { id })
|
||||||
|
.andWhere({
|
||||||
|
date: Raw((alias) => `${alias} >= :date and ${alias} < :enddate`, {
|
||||||
|
date: dateLastMonth,
|
||||||
|
enddate: dateMonth,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.getRawOne()
|
||||||
|
|
||||||
|
const pendingAmountBeforeLastMounth = await pendingCreationRepository
|
||||||
|
.createQueryBuilder('login_pending_tasks_admin')
|
||||||
|
.select('SUM(login_pending_tasks_admin.amount)', 'sum')
|
||||||
|
.where('login_pending_tasks_admin.userId = :id', { id })
|
||||||
|
.andWhere({
|
||||||
|
date: Raw((alias) => `${alias} >= :date and ${alias} < :enddate`, {
|
||||||
|
date: dateBeforeLastMonth,
|
||||||
|
enddate: dateLastMonth,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.getRawOne()
|
||||||
|
|
||||||
|
// COUNT amount from 2 tables
|
||||||
|
const usedCreationBeforeLastMonth =
|
||||||
|
(Number(createdAmountBeforeLastMonth.sum) + Number(pendingAmountBeforeLastMounth.sum)) / 10000
|
||||||
|
const usedCreationLastMonth =
|
||||||
|
(Number(createdAmountLastMonth.sum) + Number(pendingAmountLastMounth.sum)) / 10000
|
||||||
|
const usedCreationMonth =
|
||||||
|
(Number(createdAmountMonth.sum) + Number(pendingAmountMounth.sum)) / 10000
|
||||||
|
return [
|
||||||
|
1000 - usedCreationBeforeLastMonth,
|
||||||
|
1000 - usedCreationLastMonth,
|
||||||
|
1000 - usedCreationMonth,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCreationValid(creations: number[], amount: number, creationDate: Date) {
|
||||||
|
const dateMonth = moment().format('YYYY-MM')
|
||||||
|
const dateLastMonth = moment().subtract(1, 'month').format('YYYY-MM')
|
||||||
|
const dateBeforeLastMonth = moment().subtract(2, 'month').format('YYYY-MM')
|
||||||
|
const creationDateMonth = moment(creationDate).format('YYYY-MM')
|
||||||
|
|
||||||
|
let openCreation
|
||||||
|
switch (creationDateMonth) {
|
||||||
|
case dateMonth:
|
||||||
|
openCreation = creations[2]
|
||||||
|
break
|
||||||
|
case dateLastMonth:
|
||||||
|
openCreation = creations[1]
|
||||||
|
break
|
||||||
|
case dateBeforeLastMonth:
|
||||||
|
openCreation = creations[0]
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
throw new Error('CreationDate is not in last three months')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (openCreation < amount) {
|
||||||
|
throw new Error(`Open creation (${openCreation}) is less than amount (${amount})`)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
@ -161,6 +161,7 @@ export class UserResolver {
|
|||||||
const loginUserRepository = getCustomRepository(LoginUserRepository)
|
const loginUserRepository = getCustomRepository(LoginUserRepository)
|
||||||
const loginUser = await loginUserRepository.findByEmail(userEntity.email)
|
const loginUser = await loginUserRepository.findByEmail(userEntity.email)
|
||||||
const user = new User()
|
const user = new User()
|
||||||
|
user.id = userEntity.id
|
||||||
user.email = userEntity.email
|
user.email = userEntity.email
|
||||||
user.firstName = userEntity.firstName
|
user.firstName = userEntity.firstName
|
||||||
user.lastName = userEntity.lastName
|
user.lastName = userEntity.lastName
|
||||||
@ -239,6 +240,7 @@ export class UserResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const user = new User()
|
const user = new User()
|
||||||
|
user.id = userEntity.id
|
||||||
user.email = email
|
user.email = email
|
||||||
user.firstName = loginUser.firstName
|
user.firstName = loginUser.firstName
|
||||||
user.lastName = loginUser.lastName
|
user.lastName = loginUser.lastName
|
||||||
|
|||||||
@ -29,7 +29,7 @@ import { elopageWebhook } from '../webhook/elopage'
|
|||||||
// TODO implement
|
// TODO implement
|
||||||
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
|
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
|
||||||
|
|
||||||
const DB_VERSION = '0004-login_server_data'
|
const DB_VERSION = '0005-admin_tables'
|
||||||
|
|
||||||
const createServer = async (context: any = serverContext): Promise<any> => {
|
const createServer = async (context: any = serverContext): Promise<any> => {
|
||||||
// open mysql connection
|
// open mysql connection
|
||||||
|
|||||||
5
backend/src/typeorm/repository/PendingCreation.ts
Normal file
5
backend/src/typeorm/repository/PendingCreation.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { EntityRepository, Repository } from 'typeorm'
|
||||||
|
import { LoginPendingTasksAdmin } from '@entity/LoginPendingTasksAdmin'
|
||||||
|
|
||||||
|
@EntityRepository(LoginPendingTasksAdmin)
|
||||||
|
export class PendingCreationRepository extends Repository<LoginPendingTasksAdmin> {}
|
||||||
5
backend/src/typeorm/repository/TransactionCreation.ts
Normal file
5
backend/src/typeorm/repository/TransactionCreation.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { EntityRepository, Repository } from 'typeorm'
|
||||||
|
import { TransactionCreation } from '@entity/TransactionCreation'
|
||||||
|
|
||||||
|
@EntityRepository(TransactionCreation)
|
||||||
|
export class TransactionCreationRepository extends Repository<TransactionCreation> {}
|
||||||
@ -30,4 +30,17 @@ export class UserRepository extends Repository<User> {
|
|||||||
})
|
})
|
||||||
return usersIndiced
|
return usersIndiced
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findBySearchCriteria(searchCriteria: string): Promise<User[]> {
|
||||||
|
return await this.createQueryBuilder('user')
|
||||||
|
.where(
|
||||||
|
'user.firstName like :name or user.lastName like :lastName or user.email like :email',
|
||||||
|
{
|
||||||
|
name: `%${searchCriteria}%`,
|
||||||
|
lastName: `%${searchCriteria}%`,
|
||||||
|
email: `%${searchCriteria}%`,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.getMany()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
/*
|
/*
|
||||||
Elopage Webhook
|
Elopage Webhook
|
||||||
|
|
||||||
|
|||||||
@ -4139,6 +4139,11 @@ module-alias@^2.2.2:
|
|||||||
resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0"
|
resolved "https://registry.yarnpkg.com/module-alias/-/module-alias-2.2.2.tgz#151cdcecc24e25739ff0aa6e51e1c5716974c0e0"
|
||||||
integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==
|
integrity sha512-A/78XjoX2EmNvppVWEhM2oGk3x4lLxnkEA4jTbaK97QKSDjkIoOsKQlfylt/d3kKKi596Qy3NP5XrXJ6fZIC9Q==
|
||||||
|
|
||||||
|
moment@^2.29.1:
|
||||||
|
version "2.29.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||||
|
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class ServerUsersController extends AppController
|
|||||||
{
|
{
|
||||||
parent::initialize();
|
parent::initialize();
|
||||||
// uncomment in devmode to add new community server admin user, but don't!!! commit it
|
// uncomment in devmode to add new community server admin user, but don't!!! commit it
|
||||||
//$this->Auth->allow(['add', 'edit']);
|
// $this->Auth->allow(['add', 'edit']);
|
||||||
$this->Auth->deny('index');
|
$this->Auth->deny('index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,4 +4,6 @@ DB_USER=root
|
|||||||
DB_PASSWORD=
|
DB_PASSWORD=
|
||||||
DB_DATABASE=gradido_community
|
DB_DATABASE=gradido_community
|
||||||
MIGRATIONS_TABLE=migrations
|
MIGRATIONS_TABLE=migrations
|
||||||
MIGRATIONS_DIRECTORY=./migrations/
|
MIGRATIONS_DIRECTORY=./migrations/
|
||||||
|
|
||||||
|
TYPEORM_SEEDING_FACTORIES=src/factories/**/*{.ts,.js}
|
||||||
|
|||||||
@ -118,7 +118,7 @@ CMD /bin/sh -c "yarn run up"
|
|||||||
##################################################################################
|
##################################################################################
|
||||||
# PRODUCTION RESET ###############################################################
|
# PRODUCTION RESET ###############################################################
|
||||||
##################################################################################
|
##################################################################################
|
||||||
FROM production as production_reset
|
# FROM production as production_reset
|
||||||
|
|
||||||
# Run command
|
# Run command
|
||||||
CMD /bin/sh -c "yarn run reset"
|
CMD /bin/sh -c "yarn run reset"
|
||||||
|
|||||||
46
database/README.md
Normal file
46
database/README.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# database
|
||||||
|
|
||||||
|
## Project setup
|
||||||
|
```
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrade migrations production
|
||||||
|
```
|
||||||
|
yarn up
|
||||||
|
```
|
||||||
|
|
||||||
|
## Upgrade migrations development
|
||||||
|
```
|
||||||
|
yarn dev_up
|
||||||
|
```
|
||||||
|
|
||||||
|
## Downgrade migrations production
|
||||||
|
```
|
||||||
|
yarn down
|
||||||
|
```
|
||||||
|
|
||||||
|
## Downgrade migrations development
|
||||||
|
```
|
||||||
|
yarn dev_down
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Reset DB
|
||||||
|
```
|
||||||
|
yarn dev_reset
|
||||||
|
```
|
||||||
|
|
||||||
|
## Seed DB
|
||||||
|
```
|
||||||
|
yarn seed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Seeded Users
|
||||||
|
|
||||||
|
| email | password | admin |
|
||||||
|
| peter@lustig.de | `Aa12345_` | `true` |
|
||||||
|
| bibi@bloxberg.de | `Aa12345_` | `false` |
|
||||||
|
| raeuber@hotzenplotz.de | `Aa12345_` | `false` |
|
||||||
|
| bob@baumeister.de | `Aa12345_` | `false` |
|
||||||
|
|
||||||
@ -8,8 +8,8 @@ export class ServerUser extends BaseEntity {
|
|||||||
@Column({ length: 50 })
|
@Column({ length: 50 })
|
||||||
username: string
|
username: string
|
||||||
|
|
||||||
@Column({ type: 'bigint', unsigned: true })
|
@Column({ length: 255 })
|
||||||
password: BigInt
|
password: string
|
||||||
|
|
||||||
@Column({ length: 50, unique: true })
|
@Column({ length: 50, unique: true })
|
||||||
email: string
|
email: string
|
||||||
@ -23,9 +23,9 @@ export class ServerUser extends BaseEntity {
|
|||||||
@Column({ name: 'last_login', default: null, nullable: true })
|
@Column({ name: 'last_login', default: null, nullable: true })
|
||||||
lastLogin: Date
|
lastLogin: Date
|
||||||
|
|
||||||
@Column({ name: 'created', default: () => 'CURRENT_TIMESTAMP' })
|
@Column({ default: () => 'CURRENT_TIMESTAMP' })
|
||||||
created: Date
|
created: Date
|
||||||
|
|
||||||
@Column({ name: 'created', default: () => 'CURRENT_TIMESTAMP' })
|
@Column({ default: () => 'CURRENT_TIMESTAMP' })
|
||||||
modified: Date
|
modified: Date
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,22 +3,28 @@ import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
|
|||||||
// Moriz: I do not like the idea of having two user tables
|
// Moriz: I do not like the idea of having two user tables
|
||||||
@Entity('state_users')
|
@Entity('state_users')
|
||||||
export class User extends BaseEntity {
|
export class User extends BaseEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
id: number
|
id: number
|
||||||
|
|
||||||
|
@Column({ name: 'index_id', default: 0 })
|
||||||
|
indexId: number
|
||||||
|
|
||||||
|
@Column({ name: 'group_id', default: 0, unsigned: true })
|
||||||
|
groupId: number
|
||||||
|
|
||||||
@Column({ type: 'binary', length: 32, name: 'public_key' })
|
@Column({ type: 'binary', length: 32, name: 'public_key' })
|
||||||
pubkey: Buffer
|
pubkey: Buffer
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 255, nullable: true, default: null })
|
||||||
email: string
|
email: string
|
||||||
|
|
||||||
@Column({ name: 'first_name' })
|
@Column({ name: 'first_name', length: 255, nullable: true, default: null })
|
||||||
firstName: string
|
firstName: string
|
||||||
|
|
||||||
@Column({ name: 'last_name' })
|
@Column({ name: 'last_name', length: 255, nullable: true, default: null })
|
||||||
lastName: string
|
lastName: string
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 255, nullable: true, default: null })
|
||||||
username: string
|
username: string
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
|
|||||||
@ -4,22 +4,28 @@ import { UserSetting } from './UserSetting'
|
|||||||
// Moriz: I do not like the idea of having two user tables
|
// Moriz: I do not like the idea of having two user tables
|
||||||
@Entity('state_users')
|
@Entity('state_users')
|
||||||
export class User extends BaseEntity {
|
export class User extends BaseEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
id: number
|
id: number
|
||||||
|
|
||||||
|
@Column({ name: 'index_id', default: 0 })
|
||||||
|
indexId: number
|
||||||
|
|
||||||
|
@Column({ name: 'group_id', default: 0, unsigned: true })
|
||||||
|
groupId: number
|
||||||
|
|
||||||
@Column({ type: 'binary', length: 32, name: 'public_key' })
|
@Column({ type: 'binary', length: 32, name: 'public_key' })
|
||||||
pubkey: Buffer
|
pubkey: Buffer
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 255, nullable: true, default: null })
|
||||||
email: string
|
email: string
|
||||||
|
|
||||||
@Column({ name: 'first_name' })
|
@Column({ name: 'first_name', length: 255, nullable: true, default: null })
|
||||||
firstName: string
|
firstName: string
|
||||||
|
|
||||||
@Column({ name: 'last_name' })
|
@Column({ name: 'last_name', length: 255, nullable: true, default: null })
|
||||||
lastName: string
|
lastName: string
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 255, nullable: true, default: null })
|
||||||
username: string
|
username: string
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'
|
||||||
|
import { LoginUserBackup } from '../LoginUserBackup'
|
||||||
|
|
||||||
// Moriz: I do not like the idea of having two user tables
|
// Moriz: I do not like the idea of having two user tables
|
||||||
@Entity('login_users')
|
@Entity('login_users')
|
||||||
@ -53,4 +54,7 @@ export class LoginUser extends BaseEntity {
|
|||||||
|
|
||||||
@Column({ name: 'publisher_id', default: 0 })
|
@Column({ name: 'publisher_id', default: 0 })
|
||||||
publisherId: number
|
publisherId: number
|
||||||
|
|
||||||
|
@OneToOne(() => LoginUserBackup, (loginUserBackup) => loginUserBackup.loginUser)
|
||||||
|
loginUserBackup: LoginUserBackup
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,21 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, JoinColumn, OneToOne } from 'typeorm'
|
||||||
|
import { LoginUser } from '../LoginUser'
|
||||||
|
|
||||||
@Entity('login_user_backups')
|
@Entity('login_user_backups')
|
||||||
export class LoginUserBackup extends BaseEntity {
|
export class LoginUserBackup extends BaseEntity {
|
||||||
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
id: number
|
id: number
|
||||||
|
|
||||||
@Column({ name: 'user_id', nullable: false })
|
|
||||||
userId: number
|
|
||||||
|
|
||||||
@Column({ type: 'text', name: 'passphrase', nullable: false })
|
@Column({ type: 'text', name: 'passphrase', nullable: false })
|
||||||
passphrase: string
|
passphrase: string
|
||||||
|
|
||||||
|
@Column({ name: 'user_id', nullable: false })
|
||||||
|
userId: number
|
||||||
|
|
||||||
@Column({ name: 'mnemonic_type', default: -1 })
|
@Column({ name: 'mnemonic_type', default: -1 })
|
||||||
mnemonicType: number
|
mnemonicType: number
|
||||||
|
|
||||||
|
@OneToOne(() => LoginUser, (loginUser) => loginUser.loginUserBackup, { nullable: false })
|
||||||
|
@JoinColumn({ name: 'user_id' })
|
||||||
|
loginUser: LoginUser
|
||||||
}
|
}
|
||||||
|
|||||||
13
database/entity/0003-login_server_tables/LoginUserRoles.ts
Normal file
13
database/entity/0003-login_server_tables/LoginUserRoles.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column } from 'typeorm'
|
||||||
|
|
||||||
|
@Entity('login_user_roles')
|
||||||
|
export class LoginUserRoles extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Column({ name: 'user_id' })
|
||||||
|
userId: number
|
||||||
|
|
||||||
|
@Column({ name: 'role_id' })
|
||||||
|
roleId: number
|
||||||
|
}
|
||||||
25
database/entity/0005-admin_tables/LoginPendingTasksAdmin.ts
Normal file
25
database/entity/0005-admin_tables/LoginPendingTasksAdmin.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
|
||||||
|
|
||||||
|
@Entity('login_pending_tasks_admin')
|
||||||
|
export class LoginPendingTasksAdmin extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: false })
|
||||||
|
userId: number
|
||||||
|
|
||||||
|
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
|
||||||
|
created: Date
|
||||||
|
|
||||||
|
@Column({ type: 'datetime', nullable: false })
|
||||||
|
date: Date
|
||||||
|
|
||||||
|
@Column({ length: 256, nullable: true, default: null })
|
||||||
|
memo: string
|
||||||
|
|
||||||
|
@Column({ type: 'bigint', nullable: false })
|
||||||
|
amount: BigInt
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
moderator: number
|
||||||
|
}
|
||||||
1
database/entity/LoginPendingTasksAdmin.ts
Normal file
1
database/entity/LoginPendingTasksAdmin.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { LoginPendingTasksAdmin } from './0005-admin_tables/LoginPendingTasksAdmin'
|
||||||
1
database/entity/LoginUserRoles.ts
Normal file
1
database/entity/LoginUserRoles.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { LoginUserRoles } from './0003-login_server_tables/LoginUserRoles'
|
||||||
@ -2,6 +2,7 @@ import { Balance } from './Balance'
|
|||||||
import { LoginElopageBuys } from './LoginElopageBuys'
|
import { LoginElopageBuys } from './LoginElopageBuys'
|
||||||
import { LoginEmailOptIn } from './LoginEmailOptIn'
|
import { LoginEmailOptIn } from './LoginEmailOptIn'
|
||||||
import { LoginUser } from './LoginUser'
|
import { LoginUser } from './LoginUser'
|
||||||
|
import { LoginUserRoles } from './LoginUserRoles'
|
||||||
import { LoginUserBackup } from './LoginUserBackup'
|
import { LoginUserBackup } from './LoginUserBackup'
|
||||||
import { Migration } from './Migration'
|
import { Migration } from './Migration'
|
||||||
import { ServerUser } from './ServerUser'
|
import { ServerUser } from './ServerUser'
|
||||||
@ -11,12 +12,14 @@ import { TransactionSendCoin } from './TransactionSendCoin'
|
|||||||
import { User } from './User'
|
import { User } from './User'
|
||||||
import { UserSetting } from './UserSetting'
|
import { UserSetting } from './UserSetting'
|
||||||
import { UserTransaction } from './UserTransaction'
|
import { UserTransaction } from './UserTransaction'
|
||||||
|
import { LoginPendingTasksAdmin } from './LoginPendingTasksAdmin'
|
||||||
|
|
||||||
export const entities = [
|
export const entities = [
|
||||||
Balance,
|
Balance,
|
||||||
LoginElopageBuys,
|
LoginElopageBuys,
|
||||||
LoginEmailOptIn,
|
LoginEmailOptIn,
|
||||||
LoginUser,
|
LoginUser,
|
||||||
|
LoginUserRoles,
|
||||||
LoginUserBackup,
|
LoginUserBackup,
|
||||||
Migration,
|
Migration,
|
||||||
ServerUser,
|
ServerUser,
|
||||||
@ -26,4 +29,5 @@ export const entities = [
|
|||||||
User,
|
User,
|
||||||
UserSetting,
|
UserSetting,
|
||||||
UserTransaction,
|
UserTransaction,
|
||||||
|
LoginPendingTasksAdmin,
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
/* FIRST MIGRATION
|
/* FIRST MIGRATION
|
||||||
*
|
*
|
||||||
* This migration is special since it takes into account that
|
* This migration is special since it takes into account that
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
/* FIRST MIGRATION
|
/* FIRST MIGRATION
|
||||||
*
|
*
|
||||||
* This migration is special since it takes into account that
|
* This migration is special since it takes into account that
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
/* FIRST MIGRATION
|
/* FIRST MIGRATION
|
||||||
*
|
*
|
||||||
* This migration is special since it takes into account that
|
* This migration is special since it takes into account that
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
|
|
||||||
/* FIRST MIGRATION
|
/* FIRST MIGRATION
|
||||||
*
|
*
|
||||||
* This migration is special since it takes into account that
|
* This migration is special since it takes into account that
|
||||||
|
|||||||
29
database/migrations/0005-admin_tables.ts
Normal file
29
database/migrations/0005-admin_tables.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* MIGRATION FOR ADMIN INTERFACE
|
||||||
|
*
|
||||||
|
* This migration is special since it takes into account that
|
||||||
|
* the database can be setup already but also may not be.
|
||||||
|
* Therefore you will find all `CREATE TABLE` statements with
|
||||||
|
* a `IF NOT EXISTS`, all `INSERT` with an `IGNORE` and in the
|
||||||
|
* downgrade function all `DROP TABLE` with a `IF EXISTS`.
|
||||||
|
* This ensures compatibility for existing or non-existing
|
||||||
|
* databases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`login_pending_tasks_admin\` (
|
||||||
|
\`id\` int UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||||
|
\`userId\` int UNSIGNED DEFAULT 0,
|
||||||
|
\`created\` datetime NOT NULL,
|
||||||
|
\`date\` datetime NOT NULL,
|
||||||
|
\`memo\` text DEFAULT NULL,
|
||||||
|
\`amount\` bigint(20) NOT NULL,
|
||||||
|
\`moderator\` int UNSIGNED DEFAULT 0,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`DROP TABLE \`login_pending_tasks_admin\`;`)
|
||||||
|
}
|
||||||
15
database/ormconfig.js
Normal file
15
database/ormconfig.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
|
||||||
|
const CONFIG = require('./src/config')
|
||||||
|
|
||||||
|
module.export = {
|
||||||
|
name: 'default',
|
||||||
|
type: 'mysql',
|
||||||
|
host: CONFIG.DB_HOST,
|
||||||
|
port: CONFIG.DB_PORT,
|
||||||
|
username: CONFIG.DB_USER,
|
||||||
|
password: CONFIG.DB_PASSWORD,
|
||||||
|
database: CONFIG.DB_DATABASE,
|
||||||
|
seeds: ['src/seeds/**/*{.ts,.js}'],
|
||||||
|
factories: ['src/factories/**/*{.ts,.js}'],
|
||||||
|
}
|
||||||
@ -16,9 +16,12 @@
|
|||||||
"dev_up": "nodemon -w ./ --ext ts --exec ts-node src/index.ts up",
|
"dev_up": "nodemon -w ./ --ext ts --exec ts-node src/index.ts up",
|
||||||
"dev_down": "nodemon -w ./ --ext ts --exec ts-node src/index.ts down",
|
"dev_down": "nodemon -w ./ --ext ts --exec ts-node src/index.ts down",
|
||||||
"dev_reset": "nodemon -w ./ --ext ts --exec ts-node src/index.ts reset",
|
"dev_reset": "nodemon -w ./ --ext ts --exec ts-node src/index.ts reset",
|
||||||
"lint": "eslint . --ext .js,.ts"
|
"lint": "eslint . --ext .js,.ts",
|
||||||
|
"seed:config": "ts-node ./node_modules/typeorm-seeding/dist/cli.js config",
|
||||||
|
"seed": "nodemon -w ./ --ext ts --exec ts-node src/index.ts seed"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/faker": "^5.5.9",
|
||||||
"@types/node": "^16.10.3",
|
"@types/node": "^16.10.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.29.2",
|
"@typescript-eslint/eslint-plugin": "^4.29.2",
|
||||||
"@typescript-eslint/parser": "^4.29.2",
|
"@typescript-eslint/parser": "^4.29.2",
|
||||||
@ -35,10 +38,13 @@
|
|||||||
"typescript": "^4.3.5"
|
"typescript": "^4.3.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"crypto": "^1.0.1",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^10.0.0",
|
||||||
|
"faker": "^5.5.3",
|
||||||
"mysql2": "^2.3.0",
|
"mysql2": "^2.3.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"ts-mysql-migrate": "^1.0.2",
|
"ts-mysql-migrate": "^1.0.2",
|
||||||
"typeorm": "^0.2.38"
|
"typeorm": "^0.2.38",
|
||||||
|
"typeorm-seeding": "^1.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
18
database/src/factories/login-user-backup.factory.ts
Normal file
18
database/src/factories/login-user-backup.factory.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import Faker from 'faker'
|
||||||
|
import { define } from 'typeorm-seeding'
|
||||||
|
import { LoginUserBackup } from '../../entity/LoginUserBackup'
|
||||||
|
import { LoginUserBackupContext } from '../interface/UserContext'
|
||||||
|
|
||||||
|
define(LoginUserBackup, (faker: typeof Faker, context?: LoginUserBackupContext) => {
|
||||||
|
if (!context || !context.userId) {
|
||||||
|
throw new Error('LoginUserBackup: No userId present!')
|
||||||
|
}
|
||||||
|
|
||||||
|
const userBackup = new LoginUserBackup()
|
||||||
|
// TODO: Get the real passphrase
|
||||||
|
userBackup.passphrase = context.passphrase ? context.passphrase : faker.random.words(24)
|
||||||
|
userBackup.mnemonicType = context.mnemonicType ? context.mnemonicType : 2
|
||||||
|
userBackup.userId = context.userId
|
||||||
|
|
||||||
|
return userBackup
|
||||||
|
})
|
||||||
16
database/src/factories/login-user-roles.factory.ts
Normal file
16
database/src/factories/login-user-roles.factory.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import Faker from 'faker'
|
||||||
|
import { define } from 'typeorm-seeding'
|
||||||
|
import { LoginUserRoles } from '../../entity/LoginUserRoles'
|
||||||
|
import { LoginUserRolesContext } from '../interface/UserContext'
|
||||||
|
|
||||||
|
define(LoginUserRoles, (faker: typeof Faker, context?: LoginUserRolesContext) => {
|
||||||
|
if (!context) context = {}
|
||||||
|
if (!context.userId) throw new Error('LoginUserRoles: No userId present!')
|
||||||
|
if (!context.roleId) throw new Error('LoginUserRoles: No roleId present!')
|
||||||
|
|
||||||
|
const userRoles = new LoginUserRoles()
|
||||||
|
userRoles.userId = context.userId
|
||||||
|
userRoles.roleId = context.roleId
|
||||||
|
|
||||||
|
return userRoles
|
||||||
|
})
|
||||||
30
database/src/factories/login-user.factory.ts
Normal file
30
database/src/factories/login-user.factory.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import Faker from 'faker'
|
||||||
|
import { define } from 'typeorm-seeding'
|
||||||
|
import { LoginUser } from '../../entity/LoginUser'
|
||||||
|
import { randomBytes } from 'crypto'
|
||||||
|
import { LoginUserContext } from '../interface/UserContext'
|
||||||
|
|
||||||
|
define(LoginUser, (faker: typeof Faker, context?: LoginUserContext) => {
|
||||||
|
if (!context) context = {}
|
||||||
|
|
||||||
|
const user = new LoginUser()
|
||||||
|
user.email = context.email ? context.email : faker.internet.email()
|
||||||
|
user.firstName = context.firstName ? context.firstName : faker.name.firstName()
|
||||||
|
user.lastName = context.lastName ? context.lastName : faker.name.lastName()
|
||||||
|
user.username = context.username ? context.username : faker.internet.userName()
|
||||||
|
user.description = context.description ? context.description : faker.random.words(4)
|
||||||
|
// TODO Create real password and keys/hash
|
||||||
|
user.password = context.password ? context.password : BigInt(0)
|
||||||
|
user.pubKey = context.pubKey ? context.pubKey : randomBytes(32)
|
||||||
|
user.privKey = context.privKey ? context.privKey : randomBytes(80)
|
||||||
|
user.emailHash = context.emailHash ? context.emailHash : randomBytes(32)
|
||||||
|
user.createdAt = context.createdAt ? context.createdAt : faker.date.recent()
|
||||||
|
user.emailChecked = context.emailChecked ? context.emailChecked : true
|
||||||
|
user.passphraseShown = context.passphraseShown ? context.passphraseShown : false
|
||||||
|
user.language = context.language ? context.language : 'en'
|
||||||
|
user.disabled = context.disabled ? context.disabled : false
|
||||||
|
user.groupId = context.groupId ? context.groupId : 1
|
||||||
|
user.publisherId = context.publisherId ? context.publisherId : 0
|
||||||
|
|
||||||
|
return user
|
||||||
|
})
|
||||||
20
database/src/factories/server-user.factory.ts
Normal file
20
database/src/factories/server-user.factory.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import Faker from 'faker'
|
||||||
|
import { define } from 'typeorm-seeding'
|
||||||
|
import { ServerUser } from '../../entity/ServerUser'
|
||||||
|
import { ServerUserContext } from '../interface/UserContext'
|
||||||
|
|
||||||
|
define(ServerUser, (faker: typeof Faker, context?: ServerUserContext) => {
|
||||||
|
if (!context) context = {}
|
||||||
|
|
||||||
|
const user = new ServerUser()
|
||||||
|
user.username = context.username ? context.username : faker.internet.userName()
|
||||||
|
user.password = context.password ? context.password : faker.internet.password()
|
||||||
|
user.email = context.email ? context.email : faker.internet.email()
|
||||||
|
user.role = context.role ? context.role : 'admin'
|
||||||
|
user.activated = context.activated ? context.activated : 0
|
||||||
|
user.lastLogin = context.lastLogin ? context.lastLogin : faker.date.recent()
|
||||||
|
user.created = context.created ? context.created : faker.date.recent()
|
||||||
|
user.modified = context.modified ? context.modified : faker.date.recent()
|
||||||
|
|
||||||
|
return user
|
||||||
|
})
|
||||||
21
database/src/factories/user.factory.ts
Normal file
21
database/src/factories/user.factory.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import Faker from 'faker'
|
||||||
|
import { define } from 'typeorm-seeding'
|
||||||
|
import { User } from '../../entity/User'
|
||||||
|
import { randomBytes } from 'crypto'
|
||||||
|
import { UserContext } from '../interface/UserContext'
|
||||||
|
|
||||||
|
define(User, (faker: typeof Faker, context?: UserContext) => {
|
||||||
|
if (!context) context = {}
|
||||||
|
|
||||||
|
const user = new User()
|
||||||
|
user.pubkey = context.pubkey ? context.pubkey : randomBytes(32)
|
||||||
|
user.email = context.email ? context.email : faker.internet.email()
|
||||||
|
user.firstName = context.firstName ? context.firstName : faker.name.firstName()
|
||||||
|
user.lastName = context.lastName ? context.lastName : faker.name.lastName()
|
||||||
|
user.username = context.username ? context.username : faker.internet.userName()
|
||||||
|
user.disabled = context.disabled ? context.disabled : false
|
||||||
|
user.groupId = 0
|
||||||
|
user.indexId = 0
|
||||||
|
|
||||||
|
return user
|
||||||
|
})
|
||||||
@ -4,6 +4,11 @@ import { Migration } from 'ts-mysql-migrate'
|
|||||||
import CONFIG from './config'
|
import CONFIG from './config'
|
||||||
import prepare from './prepare'
|
import prepare from './prepare'
|
||||||
import connection from './typeorm/connection'
|
import connection from './typeorm/connection'
|
||||||
|
import { useSeeding, runSeeder } from 'typeorm-seeding'
|
||||||
|
import { CreatePeterLustigSeed } from './seeds/users/peter-lustig.admin.seed'
|
||||||
|
import { CreateBibiBloxbergSeed } from './seeds/users/bibi-bloxberg.seed'
|
||||||
|
import { CreateRaeuberHotzenplotzSeed } from './seeds/users/raeuber-hotzenplotz.seed'
|
||||||
|
import { CreateBobBaumeisterSeed } from './seeds/users/bob-baumeister.seed'
|
||||||
|
|
||||||
const run = async (command: string) => {
|
const run = async (command: string) => {
|
||||||
// Database actions not supported by our migration library
|
// Database actions not supported by our migration library
|
||||||
@ -45,8 +50,20 @@ const run = async (command: string) => {
|
|||||||
await migration.down() // use for downgrade script
|
await migration.down() // use for downgrade script
|
||||||
break
|
break
|
||||||
case 'reset':
|
case 'reset':
|
||||||
|
// TODO protect from production
|
||||||
await migration.reset() // use for resetting database
|
await migration.reset() // use for resetting database
|
||||||
break
|
break
|
||||||
|
case 'seed':
|
||||||
|
// TODO protect from production
|
||||||
|
await useSeeding({
|
||||||
|
root: process.cwd(),
|
||||||
|
configName: 'ormconfig.js',
|
||||||
|
})
|
||||||
|
await runSeeder(CreatePeterLustigSeed)
|
||||||
|
await runSeeder(CreateBibiBloxbergSeed)
|
||||||
|
await runSeeder(CreateRaeuberHotzenplotzSeed)
|
||||||
|
await runSeeder(CreateBobBaumeisterSeed)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unsupported command ${command}`)
|
throw new Error(`Unsupported command ${command}`)
|
||||||
}
|
}
|
||||||
|
|||||||
49
database/src/interface/UserContext.ts
Normal file
49
database/src/interface/UserContext.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
export interface UserContext {
|
||||||
|
pubkey?: Buffer
|
||||||
|
email?: string
|
||||||
|
firstName?: string
|
||||||
|
lastName?: string
|
||||||
|
username?: string
|
||||||
|
disabled?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoginUserContext {
|
||||||
|
email?: string
|
||||||
|
firstName?: string
|
||||||
|
lastName?: string
|
||||||
|
username?: string
|
||||||
|
description?: string
|
||||||
|
password?: BigInt
|
||||||
|
pubKey?: Buffer
|
||||||
|
privKey?: Buffer
|
||||||
|
emailHash?: Buffer
|
||||||
|
createdAt?: Date
|
||||||
|
emailChecked?: boolean
|
||||||
|
passphraseShown?: boolean
|
||||||
|
language?: string
|
||||||
|
disabled?: boolean
|
||||||
|
groupId?: number
|
||||||
|
publisherId?: number | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoginUserBackupContext {
|
||||||
|
userId?: number
|
||||||
|
passphrase?: string
|
||||||
|
mnemonicType?: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerUserContext {
|
||||||
|
username?: string
|
||||||
|
password?: string
|
||||||
|
email?: string
|
||||||
|
role?: string
|
||||||
|
activated?: number
|
||||||
|
lastLogin?: Date
|
||||||
|
created?: Date
|
||||||
|
modified?: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoginUserRolesContext {
|
||||||
|
userId?: number
|
||||||
|
roleId?: number
|
||||||
|
}
|
||||||
30
database/src/interface/UserInterface.ts
Normal file
30
database/src/interface/UserInterface.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export interface UserInterface {
|
||||||
|
// from login user (contains state user)
|
||||||
|
email?: string
|
||||||
|
firstName?: string
|
||||||
|
lastName?: string
|
||||||
|
username?: string
|
||||||
|
description?: string
|
||||||
|
password?: BigInt
|
||||||
|
pubKey?: Buffer
|
||||||
|
privKey?: Buffer
|
||||||
|
emailHash?: Buffer
|
||||||
|
createdAt?: Date
|
||||||
|
emailChecked?: boolean
|
||||||
|
passphraseShown?: boolean
|
||||||
|
language?: string
|
||||||
|
disabled?: boolean
|
||||||
|
groupId?: number
|
||||||
|
publisherId?: number | null
|
||||||
|
// from login user backup
|
||||||
|
passphrase?: string
|
||||||
|
mnemonicType?: number
|
||||||
|
// from server user
|
||||||
|
serverUserPassword?: string
|
||||||
|
role?: string
|
||||||
|
activated?: number
|
||||||
|
lastLogin?: Date
|
||||||
|
modified?: Date
|
||||||
|
// flag for admin
|
||||||
|
isAdmin?: boolean
|
||||||
|
}
|
||||||
11
database/src/seeds/create-user.seed.ts
Normal file
11
database/src/seeds/create-user.seed.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Factory, Seeder } from 'typeorm-seeding'
|
||||||
|
import { User } from '../../entity/User'
|
||||||
|
// import { LoginUser } from '../../entity/LoginUser'
|
||||||
|
|
||||||
|
export class CreateUserSeed implements Seeder {
|
||||||
|
public async run(factory: Factory): Promise<void> {
|
||||||
|
// const loginUser = await factory(LoginUser)().make()
|
||||||
|
// console.log(loginUser.email)
|
||||||
|
await factory(User)().create()
|
||||||
|
}
|
||||||
|
}
|
||||||
91
database/src/seeds/helpers/user-helpers.ts
Normal file
91
database/src/seeds/helpers/user-helpers.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import {
|
||||||
|
UserContext,
|
||||||
|
LoginUserContext,
|
||||||
|
LoginUserBackupContext,
|
||||||
|
ServerUserContext,
|
||||||
|
LoginUserRolesContext,
|
||||||
|
} from '../../interface/UserContext'
|
||||||
|
import { UserInterface } from '../../interface/UserInterface'
|
||||||
|
import { User } from '../../../entity/User'
|
||||||
|
import { LoginUser } from '../../../entity/LoginUser'
|
||||||
|
import { LoginUserBackup } from '../../../entity/LoginUserBackup'
|
||||||
|
import { ServerUser } from '../../../entity/ServerUser'
|
||||||
|
import { LoginUserRoles } from '../../../entity/LoginUserRoles'
|
||||||
|
import { Factory } from 'typeorm-seeding'
|
||||||
|
|
||||||
|
export const userSeeder = async (factory: Factory, userData: UserInterface): Promise<void> => {
|
||||||
|
await factory(User)(createUserContext(userData)).create()
|
||||||
|
const loginUser = await factory(LoginUser)(createLoginUserContext(userData)).create()
|
||||||
|
await factory(LoginUserBackup)(createLoginUserBackupContext(userData, loginUser)).create()
|
||||||
|
|
||||||
|
if (userData.isAdmin) {
|
||||||
|
await factory(ServerUser)(createServerUserContext(userData)).create()
|
||||||
|
|
||||||
|
// This is crazy: we just need the relation to roleId but no role at all
|
||||||
|
// It works with LoginRoles empty!!
|
||||||
|
await factory(LoginUserRoles)(createLoginUserRolesContext(loginUser)).create()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createUserContext = (context: UserInterface): UserContext => {
|
||||||
|
return {
|
||||||
|
pubkey: context.pubKey,
|
||||||
|
email: context.email,
|
||||||
|
firstName: context.firstName,
|
||||||
|
lastName: context.lastName,
|
||||||
|
username: context.username,
|
||||||
|
disabled: context.disabled,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createLoginUserContext = (context: UserInterface): LoginUserContext => {
|
||||||
|
return {
|
||||||
|
email: context.email,
|
||||||
|
firstName: context.firstName,
|
||||||
|
lastName: context.lastName,
|
||||||
|
username: context.username,
|
||||||
|
description: context.description,
|
||||||
|
password: context.password,
|
||||||
|
pubKey: context.pubKey,
|
||||||
|
privKey: context.privKey,
|
||||||
|
emailHash: context.emailHash,
|
||||||
|
createdAt: context.createdAt,
|
||||||
|
emailChecked: context.emailChecked,
|
||||||
|
passphraseShown: context.passphraseShown,
|
||||||
|
language: context.language,
|
||||||
|
disabled: context.disabled,
|
||||||
|
groupId: context.groupId,
|
||||||
|
publisherId: context.publisherId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createLoginUserBackupContext = (
|
||||||
|
context: UserInterface,
|
||||||
|
loginUser: LoginUser,
|
||||||
|
): LoginUserBackupContext => {
|
||||||
|
return {
|
||||||
|
passphrase: context.passphrase,
|
||||||
|
mnemonicType: context.mnemonicType,
|
||||||
|
userId: loginUser.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createServerUserContext = (context: UserInterface): ServerUserContext => {
|
||||||
|
return {
|
||||||
|
role: context.role,
|
||||||
|
username: context.username,
|
||||||
|
password: context.serverUserPassword,
|
||||||
|
email: context.email,
|
||||||
|
activated: context.activated,
|
||||||
|
created: context.createdAt,
|
||||||
|
lastLogin: context.lastLogin,
|
||||||
|
modified: context.modified,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createLoginUserRolesContext = (loginUser: LoginUser): LoginUserRolesContext => {
|
||||||
|
return {
|
||||||
|
userId: loginUser.id,
|
||||||
|
roleId: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
9
database/src/seeds/users/bibi-bloxberg.seed.ts
Normal file
9
database/src/seeds/users/bibi-bloxberg.seed.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Factory, Seeder } from 'typeorm-seeding'
|
||||||
|
import { bibiBloxberg } from './bibi-bloxberg'
|
||||||
|
import { userSeeder } from '../helpers/user-helpers'
|
||||||
|
|
||||||
|
export class CreateBibiBloxbergSeed implements Seeder {
|
||||||
|
public async run(factory: Factory): Promise<void> {
|
||||||
|
await userSeeder(factory, bibiBloxberg)
|
||||||
|
}
|
||||||
|
}
|
||||||
25
database/src/seeds/users/bibi-bloxberg.ts
Normal file
25
database/src/seeds/users/bibi-bloxberg.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
export const bibiBloxberg = {
|
||||||
|
email: 'bibi@bloxberg.de',
|
||||||
|
firstName: 'Bibi',
|
||||||
|
lastName: 'Bloxberg',
|
||||||
|
username: 'bibi',
|
||||||
|
description: 'Hex Hex',
|
||||||
|
password: BigInt('12825419584724616625'),
|
||||||
|
pubKey: Buffer.from('42de7e4754625b730018c3b4ea745a4d043d9d867af352d0f08871793dfa6743', 'hex'),
|
||||||
|
privKey: Buffer.from(
|
||||||
|
'60681365b6ad6fd500eae09ac8df0de6beb7554226e0ca1049e957cc6f202205b86e258bbbe98561a86bd9b986ea8b2a6c60abdff8a745f73c8932d4b6545a8da09bbcd6e18ec61a2ef30bac85f83c5d',
|
||||||
|
'hex',
|
||||||
|
),
|
||||||
|
emailHash: Buffer.from('38a0d8c8658a5681cc1180c5d9e2b2a18e4f611db8ab3ca61de4aa91ae94219b', 'hex'),
|
||||||
|
createdAt: new Date('2021-11-26T11:32:16'),
|
||||||
|
emailChecked: true,
|
||||||
|
passphraseShown: false,
|
||||||
|
language: 'de',
|
||||||
|
disabled: false,
|
||||||
|
groupId: 1,
|
||||||
|
publisherId: null,
|
||||||
|
passphrase:
|
||||||
|
'knife normal level all hurdle crucial color avoid warrior stadium road bachelor affair topple hawk pottery right afford immune two ceiling budget glance hour ',
|
||||||
|
mnemonicType: 2,
|
||||||
|
isAdmin: false,
|
||||||
|
}
|
||||||
9
database/src/seeds/users/bob-baumeister.seed.ts
Normal file
9
database/src/seeds/users/bob-baumeister.seed.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Factory, Seeder } from 'typeorm-seeding'
|
||||||
|
import { bobBaumeister } from './bob-baumeister'
|
||||||
|
import { userSeeder } from '../helpers/user-helpers'
|
||||||
|
|
||||||
|
export class CreateBobBaumeisterSeed implements Seeder {
|
||||||
|
public async run(factory: Factory): Promise<void> {
|
||||||
|
await userSeeder(factory, bobBaumeister)
|
||||||
|
}
|
||||||
|
}
|
||||||
25
database/src/seeds/users/bob-baumeister.ts
Normal file
25
database/src/seeds/users/bob-baumeister.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
export const bobBaumeister = {
|
||||||
|
email: 'bob@baumeister.de',
|
||||||
|
firstName: 'Bob',
|
||||||
|
lastName: 'der Baumeister',
|
||||||
|
username: 'bob',
|
||||||
|
description: 'Können wir das schaffen? Ja, wir schaffen das!',
|
||||||
|
password: BigInt('3296644341468822636'),
|
||||||
|
pubKey: Buffer.from('a509d9a146374fc975e3677db801ae8a4a83bff9dea96da64053ff6de6b2dd7e', 'hex'),
|
||||||
|
privKey: Buffer.from(
|
||||||
|
'd30606ac59c29058896180bebd6dcd1714dbdd697cc14b65eb4de9ef5241a5d5fc789eaab48957a887c45b7e71ab75c47fd132c14b99007891b5bdfb1026575009f0802b0126930803c113ab3f44e1be',
|
||||||
|
'hex',
|
||||||
|
),
|
||||||
|
emailHash: Buffer.from('4b8ce4e175587aaf33da19e272719da1a547daff557820191fab0c65c5a3b7f1', 'hex'),
|
||||||
|
createdAt: new Date('2021-11-26T11:36:31'),
|
||||||
|
emailChecked: true,
|
||||||
|
passphraseShown: false,
|
||||||
|
language: 'de',
|
||||||
|
disabled: false,
|
||||||
|
groupId: 1,
|
||||||
|
publisherId: null,
|
||||||
|
passphrase:
|
||||||
|
'detail master source effort unable waste tilt flush domain orchard art truck hint barrel response gate impose peanut secret merry three uncle wink resource ',
|
||||||
|
mnemonicType: 2,
|
||||||
|
isAdmin: false,
|
||||||
|
}
|
||||||
9
database/src/seeds/users/peter-lustig.admin.seed.ts
Normal file
9
database/src/seeds/users/peter-lustig.admin.seed.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Factory, Seeder } from 'typeorm-seeding'
|
||||||
|
import { peterLustig } from './peter-lustig'
|
||||||
|
import { userSeeder } from '../helpers/user-helpers'
|
||||||
|
|
||||||
|
export class CreatePeterLustigSeed implements Seeder {
|
||||||
|
public async run(factory: Factory): Promise<void> {
|
||||||
|
await userSeeder(factory, peterLustig)
|
||||||
|
}
|
||||||
|
}
|
||||||
30
database/src/seeds/users/peter-lustig.ts
Normal file
30
database/src/seeds/users/peter-lustig.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export const peterLustig = {
|
||||||
|
email: 'peter@lustig.de',
|
||||||
|
firstName: 'Peter',
|
||||||
|
lastName: 'Lustig',
|
||||||
|
username: 'peter',
|
||||||
|
description: 'Latzhose und Nickelbrille',
|
||||||
|
password: BigInt('3917921995996627700'),
|
||||||
|
pubKey: Buffer.from('7281e0ee3258b08801f3ec73e431b4519677f65c03b0382c63a913b5784ee770', 'hex'),
|
||||||
|
privKey: Buffer.from(
|
||||||
|
'3c7c0253033212ed983f6bb10ce73362a99f0bd01d4d1b21ca702d532ca32710ba36abf72a22a963b9026e764e954f441f4905b87a66861bd6b9d9689b7f8aefea66cc493e21da4244e85be81660b9c4',
|
||||||
|
'hex',
|
||||||
|
),
|
||||||
|
emailHash: Buffer.from('9f700e6f6ec351a140b674c0edd4479509697b023bd8bee8826915ef6c2af036', 'hex'),
|
||||||
|
createdAt: new Date('2020-11-25T10:48:43'),
|
||||||
|
emailChecked: true,
|
||||||
|
passphraseShown: false,
|
||||||
|
language: 'de',
|
||||||
|
disabled: false,
|
||||||
|
groupId: 1,
|
||||||
|
publisherId: null,
|
||||||
|
passphrase:
|
||||||
|
'okay property choice naive calm present weird increase stuff royal vibrant frame attend wood one else tribe pull hedgehog woman kitchen hawk snack smart ',
|
||||||
|
mnemonicType: 2,
|
||||||
|
role: 'admin',
|
||||||
|
serverUserPassword: '$2y$10$TzIWLeZoKs251gwrhSQmHeKhKI/EQ4EV5ClfAT8Ufnb4lcUXPa5X.',
|
||||||
|
activated: 1,
|
||||||
|
lastLogin: new Date('2021-10-27T12:25:57'),
|
||||||
|
modified: new Date('2021-09-27T12:25:57'),
|
||||||
|
isAdmin: true,
|
||||||
|
}
|
||||||
9
database/src/seeds/users/raeuber-hotzenplotz.seed.ts
Normal file
9
database/src/seeds/users/raeuber-hotzenplotz.seed.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Factory, Seeder } from 'typeorm-seeding'
|
||||||
|
import { raeuberHotzenplotz } from './raeuber-hotzenplotz'
|
||||||
|
import { userSeeder } from '../helpers/user-helpers'
|
||||||
|
|
||||||
|
export class CreateRaeuberHotzenplotzSeed implements Seeder {
|
||||||
|
public async run(factory: Factory): Promise<void> {
|
||||||
|
await userSeeder(factory, raeuberHotzenplotz)
|
||||||
|
}
|
||||||
|
}
|
||||||
25
database/src/seeds/users/raeuber-hotzenplotz.ts
Normal file
25
database/src/seeds/users/raeuber-hotzenplotz.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
export const raeuberHotzenplotz = {
|
||||||
|
email: 'raeuber@hotzenplotz.de',
|
||||||
|
firstName: 'Räuber',
|
||||||
|
lastName: 'Hotzenplotz',
|
||||||
|
username: 'räuber',
|
||||||
|
description: 'Pfefferpistole',
|
||||||
|
password: BigInt('12123692783243004812'),
|
||||||
|
pubKey: Buffer.from('d7c70f94234dff071d982aa8f41583876c356599773b5911b39080da2b8c2d2b', 'hex'),
|
||||||
|
privKey: Buffer.from(
|
||||||
|
'c4ede7e7e65acd4cc0a2d91136ee8f753c6903b3594798afde341092b21a4c1589f296d43c6e7adcd7602fcc2a2bcbf74c9f42453ad49cc5186eadf654bbd2c5fa9aa027f152592819246da896ebfcd2',
|
||||||
|
'hex',
|
||||||
|
),
|
||||||
|
emailHash: Buffer.from('ec8d34112adb40ff2f6538b05660b03440372690f034cd7d6322d17020233c77', 'hex'),
|
||||||
|
createdAt: new Date('2021-11-26T11:32:16'),
|
||||||
|
emailChecked: true,
|
||||||
|
passphraseShown: false,
|
||||||
|
language: 'de',
|
||||||
|
disabled: false,
|
||||||
|
groupId: 1,
|
||||||
|
publisherId: null,
|
||||||
|
passphrase:
|
||||||
|
'gospel trip tenant mouse spider skill auto curious man video chief response same little over expire drum display fancy clinic keen throw urge basket ',
|
||||||
|
mnemonicType: 2,
|
||||||
|
isAdmin: false,
|
||||||
|
}
|
||||||
@ -122,6 +122,11 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e"
|
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e"
|
||||||
integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
|
integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
|
||||||
|
|
||||||
|
"@types/faker@^5.5.9":
|
||||||
|
version "5.5.9"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/faker/-/faker-5.5.9.tgz#588ede92186dc557bff8341d294335d50d255f0c"
|
||||||
|
integrity sha512-uCx6mP3UY5SIO14XlspxsGjgaemrxpssJI0Ol+GfhxtcKpv9pgRZYsS4eeKeHVLje6Qtc8lGszuBI461+gVZBA==
|
||||||
|
|
||||||
"@types/json-schema@^7.0.7":
|
"@types/json-schema@^7.0.7":
|
||||||
version "7.0.9"
|
version "7.0.9"
|
||||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
|
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
|
||||||
@ -457,7 +462,7 @@ callsites@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
|
||||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||||
|
|
||||||
camelcase@^5.3.1:
|
camelcase@^5.0.0, camelcase@^5.3.1:
|
||||||
version "5.3.1"
|
version "5.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||||
@ -473,7 +478,7 @@ chalk@^1.1.1:
|
|||||||
strip-ansi "^3.0.0"
|
strip-ansi "^3.0.0"
|
||||||
supports-color "^2.0.0"
|
supports-color "^2.0.0"
|
||||||
|
|
||||||
chalk@^2.0.0:
|
chalk@^2.0.0, chalk@^2.4.2:
|
||||||
version "2.4.2"
|
version "2.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
|
||||||
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
|
||||||
@ -523,6 +528,13 @@ cli-boxes@^2.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
|
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
|
||||||
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
|
integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
|
||||||
|
|
||||||
|
cli-cursor@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
|
||||||
|
integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
|
||||||
|
dependencies:
|
||||||
|
restore-cursor "^3.1.0"
|
||||||
|
|
||||||
cli-highlight@^2.1.11:
|
cli-highlight@^2.1.11:
|
||||||
version "2.1.11"
|
version "2.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf"
|
resolved "https://registry.yarnpkg.com/cli-highlight/-/cli-highlight-2.1.11.tgz#49736fa452f0aaf4fae580e30acb26828d2dc1bf"
|
||||||
@ -535,6 +547,20 @@ cli-highlight@^2.1.11:
|
|||||||
parse5-htmlparser2-tree-adapter "^6.0.0"
|
parse5-htmlparser2-tree-adapter "^6.0.0"
|
||||||
yargs "^16.0.0"
|
yargs "^16.0.0"
|
||||||
|
|
||||||
|
cli-spinners@^2.2.0:
|
||||||
|
version "2.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d"
|
||||||
|
integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==
|
||||||
|
|
||||||
|
cliui@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1"
|
||||||
|
integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==
|
||||||
|
dependencies:
|
||||||
|
string-width "^4.2.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
wrap-ansi "^6.2.0"
|
||||||
|
|
||||||
cliui@^7.0.2:
|
cliui@^7.0.2:
|
||||||
version "7.0.4"
|
version "7.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
|
||||||
@ -551,6 +577,11 @@ clone-response@^1.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-response "^1.0.0"
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
|
clone@^1.0.2:
|
||||||
|
version "1.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
|
||||||
|
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
|
||||||
|
|
||||||
color-convert@^1.9.0:
|
color-convert@^1.9.0:
|
||||||
version "1.9.3"
|
version "1.9.3"
|
||||||
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
|
||||||
@ -616,6 +647,11 @@ crypto-random-string@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
|
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
|
||||||
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
|
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
|
||||||
|
|
||||||
|
crypto@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037"
|
||||||
|
integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==
|
||||||
|
|
||||||
debug@^2.2.0, debug@^2.6.9:
|
debug@^2.2.0, debug@^2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||||
@ -637,6 +673,11 @@ debug@^4.0.1, debug@^4.1.1, debug@^4.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "2.1.2"
|
ms "2.1.2"
|
||||||
|
|
||||||
|
decamelize@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
|
||||||
|
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
|
||||||
|
|
||||||
decompress-response@^3.3.0:
|
decompress-response@^3.3.0:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
|
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
|
||||||
@ -654,6 +695,13 @@ deep-is@^0.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||||
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
||||||
|
|
||||||
|
defaults@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
|
||||||
|
integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
|
||||||
|
dependencies:
|
||||||
|
clone "^1.0.2"
|
||||||
|
|
||||||
defer-to-connect@^1.0.1:
|
defer-to-connect@^1.0.1:
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
||||||
@ -1002,6 +1050,16 @@ esutils@^2.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
|
||||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||||
|
|
||||||
|
faker@4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/faker/-/faker-4.1.0.tgz#1e45bbbecc6774b3c195fad2835109c6d748cc3f"
|
||||||
|
integrity sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8=
|
||||||
|
|
||||||
|
faker@^5.5.3:
|
||||||
|
version "5.5.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e"
|
||||||
|
integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g==
|
||||||
|
|
||||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||||
@ -1066,6 +1124,14 @@ find-up@^2.0.0, find-up@^2.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
locate-path "^2.0.0"
|
locate-path "^2.0.0"
|
||||||
|
|
||||||
|
find-up@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
|
||||||
|
integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
|
||||||
|
dependencies:
|
||||||
|
locate-path "^5.0.0"
|
||||||
|
path-exists "^4.0.0"
|
||||||
|
|
||||||
flat-cache@^3.0.4:
|
flat-cache@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
|
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
|
||||||
@ -1106,7 +1172,7 @@ generate-function@^2.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-property "^1.0.2"
|
is-property "^1.0.2"
|
||||||
|
|
||||||
get-caller-file@^2.0.5:
|
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||||
@ -1141,6 +1207,18 @@ glob-parent@^5.1.2, glob-parent@~5.1.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-glob "^4.0.1"
|
is-glob "^4.0.1"
|
||||||
|
|
||||||
|
glob@7.1.6:
|
||||||
|
version "7.1.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||||
|
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
inflight "^1.0.4"
|
||||||
|
inherits "2"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
once "^1.3.0"
|
||||||
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
glob@^7.1.3:
|
glob@^7.1.3:
|
||||||
version "7.1.7"
|
version "7.1.7"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
|
||||||
@ -1434,6 +1512,11 @@ is-installed-globally@^0.3.1:
|
|||||||
global-dirs "^2.0.1"
|
global-dirs "^2.0.1"
|
||||||
is-path-inside "^3.0.1"
|
is-path-inside "^3.0.1"
|
||||||
|
|
||||||
|
is-interactive@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
|
||||||
|
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
|
||||||
|
|
||||||
is-negative-zero@^2.0.1:
|
is-negative-zero@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
|
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24"
|
||||||
@ -1605,6 +1688,13 @@ locate-path@^2.0.0:
|
|||||||
p-locate "^2.0.0"
|
p-locate "^2.0.0"
|
||||||
path-exists "^3.0.0"
|
path-exists "^3.0.0"
|
||||||
|
|
||||||
|
locate-path@^5.0.0:
|
||||||
|
version "5.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
|
||||||
|
integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
|
||||||
|
dependencies:
|
||||||
|
p-locate "^4.1.0"
|
||||||
|
|
||||||
lodash.clonedeep@^4.5.0:
|
lodash.clonedeep@^4.5.0:
|
||||||
version "4.5.0"
|
version "4.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
|
||||||
@ -1620,6 +1710,13 @@ lodash.truncate@^4.4.2:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||||
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
|
||||||
|
|
||||||
|
log-symbols@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4"
|
||||||
|
integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==
|
||||||
|
dependencies:
|
||||||
|
chalk "^2.4.2"
|
||||||
|
|
||||||
long@^4.0.0:
|
long@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28"
|
||||||
@ -1675,6 +1772,11 @@ micromatch@^4.0.4:
|
|||||||
braces "^3.0.1"
|
braces "^3.0.1"
|
||||||
picomatch "^2.2.3"
|
picomatch "^2.2.3"
|
||||||
|
|
||||||
|
mimic-fn@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||||
|
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||||
|
|
||||||
mimic-response@^1.0.0, mimic-response@^1.0.1:
|
mimic-response@^1.0.0, mimic-response@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||||
@ -1712,6 +1814,11 @@ ms@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
|
mute-stream@0.0.8:
|
||||||
|
version "0.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
|
||||||
|
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
|
||||||
|
|
||||||
mysql2@^2.3.0:
|
mysql2@^2.3.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-2.3.0.tgz#600f5cc27e397dfb77b59eac93666434f88e8079"
|
resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-2.3.0.tgz#600f5cc27e397dfb77b59eac93666434f88e8079"
|
||||||
@ -1841,6 +1948,13 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
|
onetime@^5.1.0:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
|
||||||
|
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
|
||||||
|
dependencies:
|
||||||
|
mimic-fn "^2.1.0"
|
||||||
|
|
||||||
optionator@^0.9.1:
|
optionator@^0.9.1:
|
||||||
version "0.9.1"
|
version "0.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
||||||
@ -1853,6 +1967,20 @@ optionator@^0.9.1:
|
|||||||
type-check "^0.4.0"
|
type-check "^0.4.0"
|
||||||
word-wrap "^1.2.3"
|
word-wrap "^1.2.3"
|
||||||
|
|
||||||
|
ora@4.0.3:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/ora/-/ora-4.0.3.tgz#752a1b7b4be4825546a7a3d59256fa523b6b6d05"
|
||||||
|
integrity sha512-fnDebVFyz309A73cqCipVL1fBZewq4vwgSHfxh43vVy31mbyoQ8sCH3Oeaog/owYOs/lLlGVPCISQonTneg6Pg==
|
||||||
|
dependencies:
|
||||||
|
chalk "^3.0.0"
|
||||||
|
cli-cursor "^3.1.0"
|
||||||
|
cli-spinners "^2.2.0"
|
||||||
|
is-interactive "^1.0.0"
|
||||||
|
log-symbols "^3.0.0"
|
||||||
|
mute-stream "0.0.8"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
wcwidth "^1.0.1"
|
||||||
|
|
||||||
p-cancelable@^1.0.0:
|
p-cancelable@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
||||||
@ -1865,6 +1993,13 @@ p-limit@^1.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-try "^1.0.0"
|
p-try "^1.0.0"
|
||||||
|
|
||||||
|
p-limit@^2.2.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||||
|
integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
|
||||||
|
dependencies:
|
||||||
|
p-try "^2.0.0"
|
||||||
|
|
||||||
p-locate@^2.0.0:
|
p-locate@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
|
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
|
||||||
@ -1872,11 +2007,23 @@ p-locate@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-limit "^1.1.0"
|
p-limit "^1.1.0"
|
||||||
|
|
||||||
|
p-locate@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
|
||||||
|
integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
|
||||||
|
dependencies:
|
||||||
|
p-limit "^2.2.0"
|
||||||
|
|
||||||
p-try@^1.0.0:
|
p-try@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
|
||||||
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
|
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
|
||||||
|
|
||||||
|
p-try@^2.0.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||||
|
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||||
|
|
||||||
package-json@^6.3.0:
|
package-json@^6.3.0:
|
||||||
version "6.5.0"
|
version "6.5.0"
|
||||||
resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
|
resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
|
||||||
@ -1929,6 +2076,11 @@ path-exists@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
|
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
|
||||||
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
|
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
|
||||||
|
|
||||||
|
path-exists@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
|
||||||
|
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||||
|
|
||||||
path-is-absolute@^1.0.0:
|
path-is-absolute@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||||
@ -2094,7 +2246,7 @@ readdirp@~3.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
picomatch "^2.2.1"
|
picomatch "^2.2.1"
|
||||||
|
|
||||||
reflect-metadata@^0.1.13:
|
reflect-metadata@0.1.13, reflect-metadata@^0.1.13:
|
||||||
version "0.1.13"
|
version "0.1.13"
|
||||||
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
|
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
|
||||||
integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
|
integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
|
||||||
@ -2128,6 +2280,11 @@ require-from-string@^2.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||||
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
|
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
|
||||||
|
|
||||||
|
require-main-filename@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b"
|
||||||
|
integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==
|
||||||
|
|
||||||
resolve-from@^4.0.0:
|
resolve-from@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
|
||||||
@ -2148,6 +2305,14 @@ responselike@^1.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lowercase-keys "^1.0.0"
|
lowercase-keys "^1.0.0"
|
||||||
|
|
||||||
|
restore-cursor@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
|
||||||
|
integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
|
||||||
|
dependencies:
|
||||||
|
onetime "^5.1.0"
|
||||||
|
signal-exit "^3.0.2"
|
||||||
|
|
||||||
reusify@^1.0.4:
|
reusify@^1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||||
@ -2216,6 +2381,11 @@ seq-queue@^0.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e"
|
resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e"
|
||||||
integrity sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=
|
integrity sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=
|
||||||
|
|
||||||
|
set-blocking@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||||
|
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||||
|
|
||||||
sha.js@^2.4.11:
|
sha.js@^2.4.11:
|
||||||
version "2.4.11"
|
version "2.4.11"
|
||||||
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
|
resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7"
|
||||||
@ -2532,6 +2702,18 @@ typedarray-to-buffer@^3.1.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
is-typedarray "^1.0.0"
|
is-typedarray "^1.0.0"
|
||||||
|
|
||||||
|
typeorm-seeding@^1.6.1:
|
||||||
|
version "1.6.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/typeorm-seeding/-/typeorm-seeding-1.6.1.tgz#4fe3a1aec9a611007d1135419cde286cced8defd"
|
||||||
|
integrity sha512-xJIW1pp72hv6npPqbQ7xDvawcDmS60EDUjK++UCfiqT0WE4xTzCn+QK1ZijLkD3GYCqFPuFt4nmeyRJn6VO2Vw==
|
||||||
|
dependencies:
|
||||||
|
chalk "^4.0.0"
|
||||||
|
faker "4.1.0"
|
||||||
|
glob "7.1.6"
|
||||||
|
ora "4.0.3"
|
||||||
|
reflect-metadata "0.1.13"
|
||||||
|
yargs "15.3.1"
|
||||||
|
|
||||||
typeorm@^0.2.38:
|
typeorm@^0.2.38:
|
||||||
version "0.2.38"
|
version "0.2.38"
|
||||||
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.38.tgz#2af08079919f6ab04cd17017f9faa2c8d5cd566f"
|
resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.38.tgz#2af08079919f6ab04cd17017f9faa2c8d5cd566f"
|
||||||
@ -2635,6 +2817,13 @@ validate-npm-package-license@^3.0.1:
|
|||||||
spdx-correct "^3.0.0"
|
spdx-correct "^3.0.0"
|
||||||
spdx-expression-parse "^3.0.0"
|
spdx-expression-parse "^3.0.0"
|
||||||
|
|
||||||
|
wcwidth@^1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
|
||||||
|
integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
|
||||||
|
dependencies:
|
||||||
|
defaults "^1.0.3"
|
||||||
|
|
||||||
which-boxed-primitive@^1.0.2:
|
which-boxed-primitive@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
|
||||||
@ -2646,6 +2835,11 @@ which-boxed-primitive@^1.0.2:
|
|||||||
is-string "^1.0.5"
|
is-string "^1.0.5"
|
||||||
is-symbol "^1.0.3"
|
is-symbol "^1.0.3"
|
||||||
|
|
||||||
|
which-module@^2.0.0:
|
||||||
|
version "2.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||||
|
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||||
|
|
||||||
which@^2.0.1:
|
which@^2.0.1:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
|
||||||
@ -2665,6 +2859,15 @@ word-wrap@^1.2.3:
|
|||||||
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
|
||||||
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
|
||||||
|
|
||||||
|
wrap-ansi@^6.2.0:
|
||||||
|
version "6.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
|
||||||
|
integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
|
||||||
|
dependencies:
|
||||||
|
ansi-styles "^4.0.0"
|
||||||
|
string-width "^4.1.0"
|
||||||
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
wrap-ansi@^7.0.0:
|
wrap-ansi@^7.0.0:
|
||||||
version "7.0.0"
|
version "7.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
|
||||||
@ -2707,6 +2910,11 @@ xmlbuilder@~11.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
|
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
|
||||||
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
|
integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
|
||||||
|
|
||||||
|
y18n@^4.0.0:
|
||||||
|
version "4.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||||
|
integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
|
||||||
|
|
||||||
y18n@^5.0.5:
|
y18n@^5.0.5:
|
||||||
version "5.0.8"
|
version "5.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
|
||||||
@ -2731,11 +2939,36 @@ yargonaut@^1.1.4:
|
|||||||
figlet "^1.1.1"
|
figlet "^1.1.1"
|
||||||
parent-require "^1.0.0"
|
parent-require "^1.0.0"
|
||||||
|
|
||||||
|
yargs-parser@^18.1.1:
|
||||||
|
version "18.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0"
|
||||||
|
integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==
|
||||||
|
dependencies:
|
||||||
|
camelcase "^5.0.0"
|
||||||
|
decamelize "^1.2.0"
|
||||||
|
|
||||||
yargs-parser@^20.2.2:
|
yargs-parser@^20.2.2:
|
||||||
version "20.2.9"
|
version "20.2.9"
|
||||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
|
||||||
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
||||||
|
|
||||||
|
yargs@15.3.1:
|
||||||
|
version "15.3.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.3.1.tgz#9505b472763963e54afe60148ad27a330818e98b"
|
||||||
|
integrity sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==
|
||||||
|
dependencies:
|
||||||
|
cliui "^6.0.0"
|
||||||
|
decamelize "^1.2.0"
|
||||||
|
find-up "^4.1.0"
|
||||||
|
get-caller-file "^2.0.1"
|
||||||
|
require-directory "^2.1.1"
|
||||||
|
require-main-filename "^2.0.0"
|
||||||
|
set-blocking "^2.0.0"
|
||||||
|
string-width "^4.2.0"
|
||||||
|
which-module "^2.0.0"
|
||||||
|
y18n "^4.0.0"
|
||||||
|
yargs-parser "^18.1.1"
|
||||||
|
|
||||||
yargs@^16.0.0:
|
yargs@^16.0.0:
|
||||||
version "16.2.0"
|
version "16.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
|
||||||
|
|||||||
@ -114,6 +114,11 @@
|
|||||||
"message": "hallo gradido !!",
|
"message": "hallo gradido !!",
|
||||||
"overview": "Übersicht",
|
"overview": "Übersicht",
|
||||||
"privacy_policy": "Datenschutzerklärung",
|
"privacy_policy": "Datenschutzerklärung",
|
||||||
|
"publisher": {
|
||||||
|
"infoNoRegister": "Dies ist für die Registrieung nicht nötig!",
|
||||||
|
"infoText": "Trage hier die ID des Herausgebers ein. Wenn du keine ID hast dann bitte leer lassen.",
|
||||||
|
"publisherId": "PublisherID"
|
||||||
|
},
|
||||||
"send": "Senden",
|
"send": "Senden",
|
||||||
"settings": {
|
"settings": {
|
||||||
"coinanimation": {
|
"coinanimation": {
|
||||||
|
|||||||
@ -114,6 +114,11 @@
|
|||||||
"message": "hello gradido !!",
|
"message": "hello gradido !!",
|
||||||
"overview": "Overview",
|
"overview": "Overview",
|
||||||
"privacy_policy": "Privacy policy",
|
"privacy_policy": "Privacy policy",
|
||||||
|
"publisher": {
|
||||||
|
"infoNoRegister": "This is not necessary for registration!",
|
||||||
|
"infoText": "Enter the ID of the publisher here. If you do not have an ID, please leave it blank.",
|
||||||
|
"publisherId": "PublisherID"
|
||||||
|
},
|
||||||
"send": "Send",
|
"send": "Send",
|
||||||
"settings": {
|
"settings": {
|
||||||
"coinanimation": {
|
"coinanimation": {
|
||||||
|
|||||||
@ -11,6 +11,7 @@ const {
|
|||||||
coinanimation,
|
coinanimation,
|
||||||
newsletterState,
|
newsletterState,
|
||||||
publisherId,
|
publisherId,
|
||||||
|
isAdmin,
|
||||||
community,
|
community,
|
||||||
hasElopage,
|
hasElopage,
|
||||||
} = mutations
|
} = mutations
|
||||||
@ -104,6 +105,14 @@ describe('Vuex store', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('isAdmin', () => {
|
||||||
|
it('sets the state of isAdmin', () => {
|
||||||
|
const state = { isAdmin: null }
|
||||||
|
isAdmin(state, true)
|
||||||
|
expect(state.isAdmin).toEqual(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('community', () => {
|
describe('community', () => {
|
||||||
it('sets the state of community', () => {
|
it('sets the state of community', () => {
|
||||||
const state = {}
|
const state = {}
|
||||||
|
|||||||
@ -164,6 +164,11 @@ describe('Register', () => {
|
|||||||
expect(wrapper.find('#registerCheckbox').exists()).toBeTruthy()
|
expect(wrapper.find('#registerCheckbox').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('has PublisherId input fields', () => {
|
||||||
|
wrapper.find('.publisherCollaps').trigger('click')
|
||||||
|
expect(wrapper.find('#publisherid').exists()).toBe(true)
|
||||||
|
})
|
||||||
|
|
||||||
it('has disabled submit button when not completely filled', () => {
|
it('has disabled submit button when not completely filled', () => {
|
||||||
expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled')
|
expect(wrapper.find('button[type="submit"]').attributes('disabled')).toBe('disabled')
|
||||||
})
|
})
|
||||||
@ -213,6 +218,11 @@ describe('Register', () => {
|
|||||||
wrapper.find('#registerLastname').setValue('Mustermann')
|
wrapper.find('#registerLastname').setValue('Mustermann')
|
||||||
wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net')
|
wrapper.find('#Email-input-field').setValue('max.mustermann@gradido.net')
|
||||||
wrapper.find('.language-switch-select').findAll('option').at(1).setSelected()
|
wrapper.find('.language-switch-select').findAll('option').at(1).setSelected()
|
||||||
|
wrapper.find('#publisherid').setValue('12345')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('commits publisherId to store', () => {
|
||||||
|
expect(mockStoreCommit).toBeCalledWith('publisherId', 12345)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has enabled submit button when completely filled', () => {
|
it('has enabled submit button when completely filled', () => {
|
||||||
|
|||||||
@ -117,8 +117,44 @@
|
|||||||
{{ messageError }}
|
{{ messageError }}
|
||||||
</span>
|
</span>
|
||||||
</b-alert>
|
</b-alert>
|
||||||
|
<b-row v-b-toggle:my-collapse class="text-muted shadow-sm p-3 publisherCollaps">
|
||||||
|
<b-col>
|
||||||
|
{{ $t('publisher.publisherId') }} : {{ $store.state.publisherId }}
|
||||||
|
</b-col>
|
||||||
|
<b-col class="text-right">
|
||||||
|
<b-icon icon="chevron-down" aria-hidden="true"></b-icon>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
<b-row>
|
||||||
|
<b-col>
|
||||||
|
<b-collapse id="my-collapse" class="">
|
||||||
|
<b-input-group class="shadow-sm p-2 bg-white rounded">
|
||||||
|
<b-input-group-prepend is-text>
|
||||||
|
<b-icon icon="person-fill"></b-icon>
|
||||||
|
</b-input-group-prepend>
|
||||||
|
<b-form-input
|
||||||
|
id="publisherid"
|
||||||
|
type="text"
|
||||||
|
placeholder="Publisher ID"
|
||||||
|
v-model="publisherId"
|
||||||
|
@input="commitStore(publisherId)"
|
||||||
|
></b-form-input>
|
||||||
|
</b-input-group>
|
||||||
|
<div
|
||||||
|
v-b-toggle:my-collapse
|
||||||
|
class="text-center mt-1 shadow-lg p-3 mb-5 rounded"
|
||||||
|
>
|
||||||
|
{{ $t('publisher.infoText') }}
|
||||||
|
<span class="text-dark">{{ $t('publisher.infoNoRegister') }}</span>
|
||||||
|
<div class="text-center">
|
||||||
|
<b-icon icon="chevron-up" aria-hidden="true"></b-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</b-collapse>
|
||||||
|
</b-col>
|
||||||
|
</b-row>
|
||||||
|
|
||||||
<div class="text-center">
|
<div class="text-center mt-5">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<router-link class="test-button-back" to="/login">
|
<router-link class="test-button-back" to="/login">
|
||||||
<b-button variant="outline-secondary" class="mr-4">
|
<b-button variant="outline-secondary" class="mr-4">
|
||||||
@ -176,6 +212,7 @@ export default {
|
|||||||
showError: false,
|
showError: false,
|
||||||
messageError: '',
|
messageError: '',
|
||||||
register: true,
|
register: true,
|
||||||
|
publisherId: this.$store.state.publisherId,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -188,6 +225,9 @@ export default {
|
|||||||
getValidationState({ dirty, validated, valid = null }) {
|
getValidationState({ dirty, validated, valid = null }) {
|
||||||
return dirty || validated ? valid : null
|
return dirty || validated ? valid : null
|
||||||
},
|
},
|
||||||
|
commitStore(val) {
|
||||||
|
this.$store.commit('publisherId', val)
|
||||||
|
},
|
||||||
async onSubmit() {
|
async onSubmit() {
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
|
|||||||
@ -6,6 +6,7 @@ PROJECT_DIR="${SCRIPT_DIR}/../"
|
|||||||
FRONTEND_DIR="${PROJECT_DIR}/frontend/"
|
FRONTEND_DIR="${PROJECT_DIR}/frontend/"
|
||||||
BACKEND_DIR="${PROJECT_DIR}/backend/"
|
BACKEND_DIR="${PROJECT_DIR}/backend/"
|
||||||
DATABASE_DIR="${PROJECT_DIR}/database/"
|
DATABASE_DIR="${PROJECT_DIR}/database/"
|
||||||
|
ADMIN_DIR="${PROJECT_DIR}/admin/"
|
||||||
|
|
||||||
# navigate to project directory
|
# navigate to project directory
|
||||||
cd ${PROJECT_DIR}
|
cd ${PROJECT_DIR}
|
||||||
@ -23,6 +24,8 @@ cd ${BACKEND_DIR}
|
|||||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||||
cd ${DATABASE_DIR}
|
cd ${DATABASE_DIR}
|
||||||
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||||
|
cd ${ADMIN_DIR}
|
||||||
|
yarn version --no-git-tag-version --no-commit-hooks --no-commit --new-version ${VERSION}
|
||||||
|
|
||||||
# generate changelog
|
# generate changelog
|
||||||
cd ${PROJECT_DIR}
|
cd ${PROJECT_DIR}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user