Merge pull request #959 from gradido/804-elopage-registration

804 elopage registration
This commit is contained in:
Hannes Heine 2021-10-14 12:37:44 +02:00 committed by GitHub
commit 5725e9c999
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 157 additions and 37 deletions

View File

@ -386,7 +386,7 @@ jobs:
report_name: Coverage Backend
type: lcov
result_path: ./coverage/lcov.info
min_coverage: 4
min_coverage: 3
token: ${{ github.token }}
##############################################################################

View File

@ -1,4 +1,4 @@
import { ArgsType, Field } from 'type-graphql'
import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType()
export default class CreateUserArgs {
@ -16,4 +16,7 @@ export default class CreateUserArgs {
@Field(() => String)
language: string
@Field(() => Int, { nullable: true })
publisherId: number
}

View File

@ -1,4 +1,4 @@
import { ArgsType, Field } from 'type-graphql'
import { ArgsType, Field, Int } from 'type-graphql'
@ArgsType()
export default class UnsecureLoginArgs {
@ -7,4 +7,7 @@ export default class UnsecureLoginArgs {
@Field(() => String)
password: string
@Field(() => Int, { nullable: true })
publisherId: number
}

View File

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import { ObjectType, Field } from 'type-graphql'
import { ObjectType, Field, Int } from 'type-graphql'
import { KlickTipp } from './KlickTipp'
@ObjectType()
@ -19,7 +19,6 @@ export class User {
this.pubkey = json.public_hex
this.language = json.language
this.publisherId = json.publisher_id
if (json.hasElopage) this.hasElopage = json.hasElopage
}
@Field(() => String)
@ -67,8 +66,8 @@ export class User {
groupId: number
*/
// what is publisherId?
@Field(() => Number)
publisherId: number
@Field(() => Int, { nullable: true })
publisherId?: number
@Field(() => Boolean)
coinanimation: boolean
@ -76,6 +75,6 @@ export class User {
@Field(() => KlickTipp)
klickTipp: KlickTipp
@Field(() => Boolean)
@Field(() => Boolean, { nullable: true })
hasElopage?: boolean
}

View File

@ -31,7 +31,10 @@ import { UserRepository } from '../../typeorm/repository/User'
export class UserResolver {
@Query(() => User)
@UseMiddleware(klicktippNewsletterStateMiddleware)
async login(@Args() { email, password }: UnsecureLoginArgs, @Ctx() context: any): Promise<User> {
async login(
@Args() { email, password, publisherId }: UnsecureLoginArgs,
@Ctx() context: any,
): Promise<User> {
email = email.trim().toLowerCase()
const result = await apiPost(CONFIG.LOGIN_API_URL + 'unsecureLogin', { email, password })
@ -45,6 +48,11 @@ export class UserResolver {
value: encode(result.data.session_id, result.data.user.public_hex),
})
const user = new User(result.data.user)
// Hack: Database Field is not validated properly and not nullable
if (user.publisherId === 0) {
user.publisherId = undefined
}
user.hasElopage = result.data.hasElopage
// read additional settings from settings table
const userRepository = getCustomRepository(UserRepository)
let userEntity: void | DbUser
@ -64,6 +72,15 @@ export class UserResolver {
throw new Error('error with cannot happen')
}
// Save publisherId if Elopage is not yet registered
if (!user.hasElopage && publisherId) {
user.publisherId = publisherId
await this.updateUserInfos(
{ publisherId },
{ sessionId: result.data.session_id, pubKey: result.data.user.public_hex },
)
}
const userSettingRepository = getCustomRepository(UserSettingRepository)
const coinanimation = await userSettingRepository
.readBoolean(userEntity.id, Setting.COIN_ANIMATION)
@ -102,7 +119,7 @@ export class UserResolver {
@Mutation(() => String)
async createUser(
@Args() { email, firstName, lastName, password, language }: CreateUserArgs,
@Args() { email, firstName, lastName, password, language, publisherId }: CreateUserArgs,
): Promise<string> {
const payload = {
email,
@ -112,7 +129,7 @@ export class UserResolver {
emailType: 2,
login_after_register: true,
language: language,
publisher_id: 0,
publisher_id: publisherId,
}
const result = await apiPost(CONFIG.LOGIN_API_URL + 'createUser', payload)
if (!result.success) {

View File

@ -24,10 +24,12 @@ export const klicktippNewsletterStateMiddleware: MiddlewareFn = async (
const result = await next()
let klickTipp = new KlickTipp({ status: 'Unsubscribed' })
if (CONFIG.KLICKTIPP) {
const klickTippUser = await getKlickTippUser(result.email)
if (klickTippUser) {
klickTipp = new KlickTipp(klickTippUser)
}
try {
const klickTippUser = await getKlickTippUser(result.email)
if (klickTippUser) {
klickTipp = new KlickTipp(klickTippUser)
}
} catch (err) {}
}
result.klickTipp = klickTipp
return result

View File

@ -1,3 +1,4 @@
ALLOW_REGISTER=true
GRAPHQL_URI=http://localhost:4000/graphql
DEFAULT_PUBLISHER_ID=2896
//BUILD_COMMIT=0000000

View File

@ -18,6 +18,10 @@ describe('SideBar', () => {
$store: {
state: {
email: 'test@example.org',
publisherId: 123,
firstName: 'test',
lastName: 'example',
hasElopage: false,
},
commit: jest.fn(),
},
@ -78,14 +82,18 @@ describe('SideBar', () => {
})
describe('static menu items', () => {
describe("member's area", () => {
describe("member's area without publisher ID", () => {
it('has a link to the elopage', () => {
expect(wrapper.findAll('li').at(0).text()).toBe('members_area')
expect(wrapper.findAll('li').at(0).text()).toContain('members_area')
})
it('links to the elopage', () => {
it('has a badge', () => {
expect(wrapper.findAll('li').at(0).text()).toContain('!')
})
it('links to the elopage registration', () => {
expect(wrapper.findAll('li').at(0).find('a').attributes('href')).toBe(
'https://elopage.com/s/gradido/sign_in?locale=en',
'https://elopage.com/s/gradido/basic-de/payment?locale=en&prid=111&pid=123&firstName=test&lastName=example&email=test@example.org',
)
})
@ -94,11 +102,27 @@ describe('SideBar', () => {
mocks.$i18n.locale = 'de'
})
it('links to the German elopage when locale is set to de', () => {
it('links to the German elopage registration when locale is set to de', () => {
expect(wrapper.findAll('li').at(0).find('a').attributes('href')).toBe(
'https://elopage.com/s/gradido/basic-de/payment?locale=de&prid=111&pid=123&firstName=test&lastName=example&email=test@example.org',
)
})
})
describe("member's area with publisher ID", () => {
beforeEach(() => {
mocks.$store.state.hasElopage = true
})
it('links to the elopage member area', () => {
expect(wrapper.findAll('li').at(0).find('a').attributes('href')).toBe(
'https://elopage.com/s/gradido/sign_in?locale=de',
)
})
it('has no badge', () => {
expect(wrapper.findAll('li').at(0).text()).not.toContain('!')
})
})
})

View File

@ -47,12 +47,9 @@
<hr class="my-2" />
<ul class="navbar-nav ml-3">
<li class="nav-item">
<a
:href="`https://elopage.com/s/gradido/sign_in?locale=${$i18n.locale}`"
class="nav-link"
target="_blank"
>
{{ $t('members_area') }}
<a :href="getElopageLink()" class="nav-link" target="_blank">
{{ $t('members_area') }}&nbsp;
<b-badge v-if="!this.$store.state.hasElopage" pill variant="danger">!</b-badge>
</a>
</li>
</ul>
@ -71,6 +68,7 @@
<script>
import NavbarToggleButton from '@/components/NavbarToggleButton'
import VueQrcode from 'vue-qrcode'
import { CONFIG } from '../../config'
export default {
name: 'sidebar',
@ -114,6 +112,16 @@ export default {
logout() {
this.$emit('logout')
},
getElopageLink() {
const pId = this.$store.state.publisherId
? this.$store.state.publisherId
: CONFIG.DEFAULT_PUBLISHER_ID
return encodeURI(
this.$store.state.hasElopage
? `https://elopage.com/s/gradido/sign_in?locale=${this.$i18n.locale}`
: `https://elopage.com/s/gradido/basic-de/payment?locale=${this.$i18n.locale}&prid=111&pid=${pId}&firstName=${this.$store.state.firstName}&lastName=${this.$store.state.lastName}&email=${this.$store.state.email}`,
)
},
},
}
</script>

View File

@ -15,6 +15,7 @@ const environment = {
NODE_ENV: process.env.NODE_ENV,
DEBUG: process.env.NODE_ENV !== 'production' || false,
PRODUCTION: process.env.NODE_ENV === 'production' || false,
DEFAULT_PUBLISHER_ID: process.env.DEFAULT_PUBLISHER_ID || 2896,
}
const server = {

View File

@ -51,6 +51,7 @@ export const registerUser = gql`
$email: String!
$password: String!
$language: String!
$publisherId: Int!
) {
createUser(
email: $email
@ -58,6 +59,7 @@ export const registerUser = gql`
lastName: $lastName
password: $password
language: $language
publisherId: $publisherId
)
}
`

View File

@ -1,8 +1,8 @@
import gql from 'graphql-tag'
export const login = gql`
query($email: String!, $password: String!) {
login(email: $email, password: $password) {
query($email: String!, $password: String!, $publisherId: Int) {
login(email: $email, password: $password, publisherId: $publisherId) {
email
username
firstName
@ -13,6 +13,8 @@ export const login = gql`
klickTipp {
newsletterState
}
hasElopage
publisherId
}
}
`

View File

@ -30,7 +30,9 @@ export const mutations = {
state.newsletterState = newsletterState
},
publisherId: (state, publisherId) => {
state.publisherId = publisherId
let pubId = parseInt(publisherId)
if (isNaN(pubId)) pubId = null
state.publisherId = pubId
},
community: (state, community) => {
state.community = community
@ -38,6 +40,9 @@ export const mutations = {
coinanimation: (state, coinanimation) => {
state.coinanimation = coinanimation
},
hasElopage: (state, hasElopage) => {
state.hasElopage = hasElopage
},
}
export const actions = {
@ -50,6 +55,8 @@ export const actions = {
commit('description', data.description)
commit('coinanimation', data.coinanimation)
commit('newsletterState', data.klickTipp.newsletterState)
commit('hasElopage', data.hasElopage)
commit('publisherId', data.publisherId)
},
logout: ({ commit, state }) => {
commit('token', null)
@ -60,6 +67,8 @@ export const actions = {
commit('description', '')
commit('coinanimation', true)
commit('newsletterState', null)
commit('hasElopage', false)
commit('publisherId', null)
localStorage.clear()
},
}
@ -81,6 +90,8 @@ export const store = new Vuex.Store({
coinanimation: true,
newsletterState: null,
community: null,
hasElopage: false,
publisherId: null,
},
getters: {},
// Syncronous mutation of the state

View File

@ -12,6 +12,7 @@ const {
newsletterState,
publisherId,
community,
hasElopage,
} = mutations
const { login, logout } = actions
@ -95,6 +96,12 @@ describe('Vuex store', () => {
publisherId(state, 42)
expect(state.publisherId).toEqual(42)
})
it('sets publisherId to null with NaN', () => {
const state = {}
publisherId(state, 'abc')
expect(state.publisherId).toEqual(null)
})
})
describe('community', () => {
@ -114,6 +121,14 @@ describe('Vuex store', () => {
})
})
})
describe('hasElopage', () => {
it('sets the state of hasElopage', () => {
const state = { hasElopage: false }
hasElopage(state, true)
expect(state.hasElopage).toBeTruthy()
})
})
})
describe('actions', () => {
@ -131,11 +146,13 @@ describe('Vuex store', () => {
klickTipp: {
newsletterState: true,
},
hasElopage: false,
publisherId: 1234,
}
it('calls eight commits', () => {
it('calls ten commits', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenCalledTimes(8)
expect(commit).toHaveBeenCalledTimes(10)
})
it('commits email', () => {
@ -177,15 +194,25 @@ describe('Vuex store', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(8, 'newsletterState', true)
})
it('commits hasElopage', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(9, 'hasElopage', false)
})
it('commits publisherId', () => {
login({ commit, state }, commitedData)
expect(commit).toHaveBeenNthCalledWith(10, 'publisherId', 1234)
})
})
describe('logout', () => {
const commit = jest.fn()
const state = {}
it('calls eight commits', () => {
it('calls ten commits', () => {
logout({ commit, state })
expect(commit).toHaveBeenCalledTimes(8)
expect(commit).toHaveBeenCalledTimes(10)
})
it('commits token', () => {
@ -228,6 +255,16 @@ describe('Vuex store', () => {
expect(commit).toHaveBeenNthCalledWith(8, 'newsletterState', null)
})
it('commits hasElopage', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(9, 'hasElopage', false)
})
it('commits publisherId', () => {
logout({ commit, state })
expect(commit).toHaveBeenNthCalledWith(10, 'publisherId', null)
})
// how to get this working?
it.skip('calls localStorage.clear()', () => {
const clearStorageMock = jest.fn()

View File

@ -45,6 +45,9 @@ describe('DashboardLayoutGdd', () => {
$store: {
state: {
email: 'user@example.org',
publisherId: 123,
firstName: 'User',
lastName: 'Example',
},
dispatch: storeDispatchMock,
commit: storeCommitMock,
@ -114,9 +117,10 @@ describe('DashboardLayoutGdd', () => {
})
it('has a link to the members area', () => {
expect(wrapper.findAll('ul').at(2).text()).toBe('members_area')
expect(wrapper.findAll('ul').at(2).text()).toContain('members_area')
expect(wrapper.findAll('ul').at(2).text()).toContain('!')
expect(wrapper.findAll('ul').at(2).find('a').attributes('href')).toBe(
'https://elopage.com/s/gradido/sign_in?locale=en',
'https://elopage.com/s/gradido/basic-de/payment?locale=en&prid=111&pid=123&firstName=User&lastName=Example&email=user@example.org',
)
})

View File

@ -44,6 +44,7 @@ describe('Login', () => {
registerUrl: 'http://localhost/vue/register',
description: 'Die lokale Entwicklungsumgebung von Gradido.',
},
publisherId: 12345,
},
},
$loading: {
@ -199,6 +200,7 @@ describe('Login', () => {
variables: {
email: 'user@example.org',
password: '1234',
publisherId: 12345,
},
}),
)

View File

@ -96,6 +96,7 @@ export default {
variables: {
email: this.form.email,
password: this.form.password,
publisherId: this.$store.state.publisherId,
},
fetchPolicy: 'network-only',
})

View File

@ -32,6 +32,7 @@ describe('Register', () => {
registerUrl: 'http://localhost/vue/register',
description: 'Die lokale Entwicklungsumgebung von Gradido.',
},
publisherId: 12345,
},
},
}
@ -216,6 +217,7 @@ describe('Register', () => {
lastName: 'Mustermann',
password: 'Aa123456_',
language: 'en',
publisherId: 12345,
},
}),
)

View File

@ -199,6 +199,7 @@ export default {
lastName: this.form.lastname,
password: this.form.password.password,
language: this.language,
publisherId: this.$store.state.publisherId,
},
})
.then(() => {

View File

@ -10,7 +10,7 @@ Poco::JSON::Object* JsonHasElopage::handle(Poco::Dynamic::Var params)
auto elopage_buy = Poco::AutoPtr<model::table::ElopageBuy>(new model::table::ElopageBuy);
result = stateSuccess();
result->set("hasElopage", elopage_buy->isExistInDB("email", mSession->getNewUser()->getModel()->getEmail()));
result->set("hasElopage", elopage_buy->isExistInDB("payer_email", mSession->getNewUser()->getModel()->getEmail()));
return result;
}

View File

@ -113,7 +113,7 @@ namespace model {
int UserHasElopageTask::run()
{
auto elopage_buy = Poco::AutoPtr<model::table::ElopageBuy>(new model::table::ElopageBuy);
bool hasElopage = elopage_buy->isExistInDB("payer_email", mEmail);
mHasElopage = elopage_buy->isExistInDB("payer_email", mEmail);
return 0;
}
}