merge changes from HH

This commit is contained in:
Moriz Wahl 2021-08-02 15:46:40 +02:00
commit f77364e053
18 changed files with 449 additions and 115 deletions

3
.gitmodules vendored
View File

@ -31,6 +31,3 @@
[submodule "login_server/src/proto"]
path = login_server/src/proto
url = https://github.com/gradido/gradido_protocol.git
[submodule "login_server/dependencies/protobuf"]
path = login_server/dependencies/protobuf
url = https://github.com/protocolbuffers/protobuf.git

View File

@ -1,4 +1,4 @@
PORT=4000
GRAPHIQL=false
// LOGIN_API_URL=http://login-server:1201/
// COMMUNITY_API_URL=http://localhost/api/
// COMMUNITY_API_URL=http://nginx/api/

View File

@ -2,35 +2,38 @@ import axios from 'axios'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const apiPost = async (url: string, payload: unknown): Promise<any> => {
try {
const result = await axios.post(url, payload)
return axios
.post(url, payload)
.then((result) => {
if (result.status !== 200) {
throw new Error('HTTP Status Error ' + result.status)
}
if (result.data.state === 'warning') {
return { success: true, result: result.data.errors }
}
if (result.data.state !== 'success') {
throw new Error(result.data.msg)
}
return { success: true, result }
} catch (error) {
})
.catch((error) => {
return { success: false, result: error }
}
})
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const apiGet = async (url: string): Promise<any> => {
try {
const result = await axios.get(url)
return axios
.get(url)
.then((result) => {
if (result.status !== 200) {
throw new Error('HTTP Status Error ' + result.status)
}
if (!['success', 'warning'].includes(result.data.state)) {
throw new Error(result.data.msg)
}
return { success: true, result }
} catch (error) {
return { success: true, result: result }
})
.catch((error) => {
// eslint-disable-next-line no-console
console.log('IN apiGet.ERROR: ' + JSON.stringify({ success: false, result: error }))
return { success: false, result: error }
}
})
}

View File

@ -8,8 +8,8 @@ const server = {
JWT_SECRET: process.env.JWT_SECRET || 'secret123',
JWT_EXPIRES_IN: process.env.JWT_EXPIRES_IN || '10m',
GRAPHIQL: process.env.GRAPHIQL === 'true' || false,
LOGIN_API_URL: process.env.LOGIN_API_URL || 'http://localhost/login_api/',
// COMMUNITY_API_URL: process.env.COMMUNITY_API_URL || 'http://localhost/api/',
LOGIN_API_URL: process.env.LOGIN_API_URL || 'http://login-server:1201/',
COMMUNITY_API_URL: process.env.COMMUNITY_API_URL || 'http://ngninx/api/',
}
// This is needed by graphql-directive-auth

View File

@ -26,6 +26,42 @@ export class UnsecureLoginArgs {
password: string
}
@ArgsType()
export class CreateUserArgs {
@Field(() => String)
email: string
@Field(() => String)
firstName: string
@Field(() => String)
lastName: string
@Field(() => String)
password: string
}
@ArgsType()
export class SendEmailArgs {
@Field(() => String)
email: string
@Field(() => Number)
emailText: number
@Field(() => String)
emailVerificationCodeType: string
}
@ArgsType()
export class GetUserInfoArgs {
@Field(() => Number)
sessionId: number
@Field(() => String)
email: string
}
@ArgsType()
export class ChangePasswordArgs {
@Field(() => Number)
@ -37,3 +73,39 @@ export class ChangePasswordArgs {
@Field(() => String)
password: string
}
@ArgsType()
export class UpdateUserInfosArgs {
@Field(() => Number)
sessionId!: number
@Field(() => String)
email!: string
@Field(() => String)
firstName?: string
@Field(() => String)
lastName?: string
@Field(() => String)
username?: string
@Field(() => String)
language?: string
@Field(() => String)
password?: string
@Field(() => String)
passwordNew?: string
}
@ArgsType()
export class CheckUsernameArgs {
@Field(() => String)
username: string
@Field(() => Number)
groupId?: number
}

View File

@ -0,0 +1,50 @@
import { ObjectType, ArgsType, Field, Int, Float } from 'type-graphql'
import { Entity, BaseEntity, Column, Double } from 'typeorm'
@ArgsType()
export class TransactionInput {
@Field(() => Number)
sessionId: number
@Field(() => Number)
firstPage: number
@Field(() => Number)
items: number
@Field(() => String)
order: string
}
@ArgsType()
export class TransactionSendArgs {
@Field(() => Number)
sessionId: number
@Field(() => String)
email: string
@Field(() => Number)
amount: number
@Field(() => String)
memo: string
}
@ArgsType()
export class TransactionCreateArgs {
@Field(() => Number)
sessionId: number
@Field(() => String)
email: string
@Field(() => Number)
amount: number
@Field(() => String)
memo: string
@Field(() => Date)
targetDate: Date
}

View File

@ -0,0 +1,26 @@
import { Entity, BaseEntity, Column } from 'typeorm'
import { ObjectType, Field } from 'type-graphql'
@Entity()
@ObjectType()
export class Balance extends BaseEntity {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
constructor(json: any) {
super()
this.balance = json.balance
this.decay = json.decay
this.decayDate = json.decay_date
}
@Field(() => Number)
@Column()
balance: number
@Field(() => Number)
@Column()
decay: number
@Field(() => String)
@Column()
decayDate: string
}

View File

@ -1,26 +0,0 @@
import { Entity, BaseEntity, PrimaryGeneratedColumn, Column } from 'typeorm'
import { ObjectType, Field, ID } from 'type-graphql'
@Entity()
@ObjectType()
export class Group extends BaseEntity {
@Field(() => ID)
@PrimaryGeneratedColumn()
id: number
@Field(() => String)
@Column({ length: 190 })
alias: string
@Field(() => String)
@Column()
name: string
@Field(() => String)
@Column('text')
description: string
@Field(() => String)
@Column()
url: string
}

View File

@ -0,0 +1,10 @@
import { Entity, BaseEntity, Column } from 'typeorm'
import { ObjectType, Field } from 'type-graphql'
@Entity()
@ObjectType()
export class Transaction extends BaseEntity {
@Field(() => String)
@Column({ length: 191 })
email: string
}

View File

@ -95,3 +95,90 @@ export class LoginViaVerificationCode extends BaseEntity {
@Column()
email: string
}
@Entity()
@ObjectType()
export class LogoutResponse extends BaseEntity {
@Field(() => String)
state: string
}
@Entity()
@ObjectType()
export class CreateResponse extends BaseEntity {
@Field(() => String)
state: string
}
@Entity()
@ObjectType()
export class SendEmailResponse extends BaseEntity {
@Field(() => String)
state: string
@Field(() => String)
msg?: string
}
@Entity()
@ObjectType()
export class Server extends BaseEntity {
@Field(() => String)
loginServerPath: string
}
@Entity()
@ObjectType()
export class ErrorData extends BaseEntity {
@Field(() => String)
messages: string
}
@Entity()
@ObjectType()
export class GetUserInfoResponse extends BaseEntity {
@Field(() => String)
state: string
@Field(() => User)
userData: User
@Field(() => Server)
server: Server
@Field(() => [ErrorData])
errors: [ErrorData]
}
@Entity()
@ObjectType()
export class ChangePasswordResponse extends BaseEntity {
@Field(() => String)
state: string
}
@Entity()
@ObjectType()
export class UpdateUserInfosResponse extends BaseEntity {
@Field(() => String)
state: string
@Field(() => Number)
validValues: number
@Field(() => [ErrorData])
errors: [ErrorData]
}
@Entity()
@ObjectType()
export class CheckUsernameResponse extends BaseEntity {
@Field(() => String)
state: string
@Field(() => String)
msg?: string
@Field(() => Number)
groupId?: number
}

View File

@ -0,0 +1,57 @@
import { Resolver, Query, /* Mutation, */ Args, Arg } from 'type-graphql'
import CONFIG from '../../config'
import {} from '../models/Transaction'
import { Balance } from '../models/Balance'
import {
TransactionCreateArgs,
TransactionInput,
TransactionSendArgs,
} from '../inputs/TransactionInput'
import { apiPost, apiGet } from '../../apis/loginAPI'
@Resolver()
export class CommunityTransactionResolver {
@Query(() => Balance)
async balance(@Arg('sessionId') sessionId: number): Promise<Balance> {
// eslint-disable-next-line no-console
console.log('IN BALANCE: URL: ' + CONFIG.COMMUNITY_API_URL + 'getBalance/' + sessionId)
const result = await apiGet(CONFIG.COMMUNITY_API_URL + 'getBalance/' + sessionId)
return new Balance(result.result.data)
}
@Query(() => String)
async transactions(
@Args() { sessionId, firstPage = 1, items = 5, order = 'DESC' }: TransactionInput,
): Promise<any> {
return apiGet(
`${CONFIG.COMMUNITY_API_URL}listTransactions/${firstPage}/${items}/${order}/${sessionId}`,
)
}
@Query(() => String)
async send(@Args() { sessionId, email, amount, memo }: TransactionSendArgs): Promise<any> {
const payload = {
session_id: sessionId,
auto_sign: true,
email: email,
amount: amount,
memo: memo,
}
return apiPost(CONFIG.COMMUNITY_API_URL + 'sendCoins/', payload)
}
@Query(() => String)
async create(
@Args() { sessionId, email, amount, memo, targetDate = new Date() }: TransactionCreateArgs,
): Promise<any> {
const payload = {
sessionId,
email,
amount,
targetDate,
memo,
auto_sign: true,
}
return apiPost(CONFIG.COMMUNITY_API_URL + 'createCoins/', payload)
}
}

View File

@ -1,23 +0,0 @@
import { Resolver, Query, Mutation, Arg } from 'type-graphql'
import { Group } from '../models/Group'
import { loginAPI, NetworkInfosResult } from '../../apis/loginAPI'
@Resolver()
export class GroupResolver {
@Query(() => [Group])
async groups(): Promise<Group[]> {
const result: NetworkInfosResult = await loginAPI.getNetworkInfos(['groups'])
const groups: Group[] = []
result.data.groups?.forEach((alias: string) => {
const group = new Group()
group.alias = alias
groups.push(group)
})
return groups
}
@Query(() => Group)
group(@Arg('id') id: string): Promise<Group | undefined> {
return Group.findOne({ where: { id } })
}
}

View File

@ -1,22 +1,30 @@
// import jwt from 'jsonwebtoken'
import { Resolver, Query, /* Mutation, */ Args, Arg } from 'type-graphql'
import CONFIG from '../../config'
import { LoginResponse, LoginViaVerificationCode } from '../models/User'
import { UnsecureLoginArgs, ChangePasswordArgs } from '../inputs/LoginUserInput'
import {
ChangePasswordResponse,
CheckUsernameResponse,
CreateResponse,
GetUserInfoResponse,
LoginResponse,
LoginViaVerificationCode,
LogoutResponse,
SendEmailResponse,
UpdateUserInfosResponse,
} from '../models/User'
import {
ChangePasswordArgs,
CheckUsernameArgs,
CreateUserArgs,
GetUserInfoArgs,
SendEmailArgs,
UnsecureLoginArgs,
UpdateUserInfosArgs,
} from '../inputs/LoginUserInput'
import { apiPost, apiGet } from '../../apis/loginAPI'
@Resolver()
export class UserResolver {
/* @Query(() => [User])
users(): Promise<User[]> {
return User.find()
} */
/* @Query(() => User)
user(@Arg('id') id: string): Promise<User | undefined> {
return User.findOne({ where: { id } })
} */
@Query(() => LoginResponse)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async login(@Args() { email, password }: UnsecureLoginArgs): Promise<any> {
@ -55,20 +63,6 @@ export class UserResolver {
// return loginResult.user ? loginResult.user : new User()
}
// forgot password request
@Query(() => String)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async sendEmail(@Arg('email') email: string): Promise<any> {
const payload = {
email,
email_text: 7,
email_verification_code_type: 'resetPassword',
}
const result = await apiPost(CONFIG.LOGIN_API_URL + 'sendEmail', payload)
if (result.success) return result.result.data.state
return result.result
}
@Query(() => LoginViaVerificationCode)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async loginViaEmailVerificationCode(@Arg('optin') optin: string): Promise<any> {
@ -85,8 +79,50 @@ export class UserResolver {
return result.result
}
@Query(() => String)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@Query(() => LogoutResponse)
async logout(@Arg('sessionId') sessionId: number): Promise<any> {
const payload = { session_id: sessionId }
const result = apiPost(CONFIG.LOGIN_API_URL + 'logout', payload);
return result
}
@Query(() => CreateResponse)
async create(@Args() { email, firstName, lastName, password }: CreateUserArgs): Promise<any> {
const payload = {
email,
first_name: firstName,
last_name: lastName,
password,
emailType: 2,
login_after_register: true,
}
return apiPost(CONFIG.LOGIN_API_URL + 'createUser', payload)
}
@Query(() => SendEmailResponse)
async sendEmail(
@Args()
{ email, emailText = 7, emailVerificationCodeType = 'resetPassword' }: SendEmailArgs,
): Promise<any> {
const payload = {
email,
email_text: emailText,
email_verification_code_type: emailVerificationCodeType,
}
return apiPost(CONFIG.LOGIN_API_URL + 'sendEmail', payload)
}
@Query(() => GetUserInfoResponse)
async getUserInfos(@Args() { sessionId, email }: GetUserInfoArgs): Promise<any> {
const payload = {
session_id: sessionId,
email: email,
ask: ['user.first_name', 'user.last_name'],
}
return apiPost(CONFIG.LOGIN_API_URL + 'getUserInfos', payload)
}
@Query(() => ChangePasswordResponse)
async changePassword(@Args() { sessionId, email, password }: ChangePasswordArgs): Promise<any> {
const payload = {
session_id: sessionId,
@ -94,8 +130,42 @@ export class UserResolver {
password,
}
const result = await apiPost(CONFIG.LOGIN_API_URL + 'resetPassword', payload)
console.log(result)
if (result.success) return result.result.data.state
return result.result
}
@Query(() => UpdateUserInfosResponse)
async updateUserInfos(
@Args()
{
sessionId,
email,
firstName,
lastName,
username,
language,
password,
passwordNew,
}: UpdateUserInfosArgs,
): Promise<any> {
const payload = {
session_id: sessionId,
email,
update: {
'User.first_name': firstName,
'User.last_name': lastName,
// 'User.description': data.description,
'User.username': username,
'User.language': language,
'User.password_old': password,
'User.password': passwordNew,
},
}
return apiPost(CONFIG.LOGIN_API_URL + 'updateUserInfos', payload)
}
@Query(() => CheckUsernameResponse)
async checkUsername(@Args() { username, groupId = 1 }: CheckUsernameArgs): Promise<any> {
return apiGet(CONFIG.LOGIN_API_URL + `checkUsername?username=${username}&group_id=${groupId}`)
}
}

View File

@ -8,6 +8,7 @@ import CONFIG from './config'
// TODO move to extern
// import { BookResolver } from './graphql/resolvers/BookResolver'
import { UserResolver } from './graphql/resolvers/UserResolver'
import { CommunityTransactionResolver } from './graphql/resolvers/CommunityTransactionResolver'
// import { GroupResolver } from './graphql/resolvers/GroupResolver'
// TODO implement
// import queryComplexity, { simpleEstimator, fieldConfigEstimator } from "graphql-query-complexity";
@ -15,7 +16,7 @@ import { UserResolver } from './graphql/resolvers/UserResolver'
async function main() {
// const connection = await createConnection()
const schema = await buildSchema({
resolvers: [/* BookResolver , GroupResolver, */ UserResolver],
resolvers: [/* BookResolver , GroupResolver, */ UserResolver, CommunityTransactionResolver],
})
// Graphiql interface

View File

@ -271,6 +271,8 @@ class AppRequestsController extends AppController
public function getBalance($session_id = 0)
{
$this->viewBuilder()->setLayout('ajax');
$this->response = $this->response->withType('application/json');
$login_result = $this->requestLogin($session_id, false);
if($login_result !== true) {
$this->set('body', $login_result);
@ -301,12 +303,16 @@ class AppRequestsController extends AppController
}
$body['decay_date'] = $now;
$this->addAdminError("AppRequests", "getBalance", $body, $user['id']);
$this->set('body', $body);
}
public function listTransactions($page = 1, $count = 25, $orderDirection = 'ASC', $session_id = 0)
{
$this->viewBuilder()->setLayout('ajax');
$this->response = $this->response->withType('application/json');
$startTime = microtime(true);
$login_result = $this->requestLogin($session_id, false);

View File

@ -6,6 +6,10 @@
* and open the template in the editor.
*/
if(isset($body['balance'])) {
$body['balance'] = $this->element('centToFloat', ['cent' => $body['balance'], 'precision' => 4]);
}
if(isset($body['decay'])) {
$body['decay'] = $this->element('centToFloat', ['cent' => $body['decay'], 'precision' => 4]);
}
?><?= json_encode($body) ?>

View File

@ -30,6 +30,7 @@ services:
target: development
networks:
- external-net
- internal-net
environment:
- NODE_ENV="development"
volumes:

@ -1 +0,0 @@
Subproject commit 0b8d13a1d4cd9be16ed8a2230577aa9c296aa1ca