Skip to content

Commit

Permalink
added webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
juicycleff committed Aug 7, 2020
1 parent 6adad43 commit 31850cc
Show file tree
Hide file tree
Showing 507 changed files with 10,534 additions and 5,206 deletions.
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ Software features
* ✅ Service Discovery (Default on Consul), supports ectd, Kubernetes
*[React SSR Starter Kit](https://github.com/juicycleff/ultimate-backend-dashboard)
* ❌ (WiP) Documentation
* (WiP) Webhooks
* (WiP) Webhooks
* ❌ (WiP) Support for language translation
* ❌ (WiP) GraphQL dataloaders

## Software stack

| |Required |Optional |
|----------------|-------------------------------|-----------------------------|
|`Store and cache`|[Event Store (Event Source Store)](https://eventstore.org), [Memcached (cache)](https://memcached.org/), [Redis (Queue)](https://redis.io/) and [MongoDB (Database)](https://www.mongodb.com/) |[ArangoDB (Database)](https://www.arangodb.com/) |
|`Store and cache`|[Event Store (Event Source Store)](https://eventstore.org), [Redis (Queue & cache)](https://redis.io/) and [MongoDB (Database)](https://www.mongodb.com/) |[ArangoDB (Database)](https://www.arangodb.com/) |
|`Stack and frameworks` |[NestJS (Server Framework)](https://nestjs.com), [NodeJS (System runtime)](https://nodejs.org), [Typescript](https://www.typescriptlang.org), [Express JS](https://expressjs.com), [Fastify](https://www.fastify.io), [GRPC](https://grpc.io/), [NestCloud](https://nestcloud.org/) and [Apollo GraphQL](https://www.apollographql.com) |none |
|`Deployment and containerization` |[Docker](https://www.docker.com/) |[Kubernetes](https://kubernetes.io/), [Azure Pipeline](https://azure.microsoft.com/en-us/services/devops/pipelines/), GitLab CI ||
|`Service Registry` |[Consul](https://consul.io/)|[Kubernetes](https://kubernetes.io/) and [etcd](https://etcd.io/)|
Expand Down Expand Up @@ -137,12 +137,10 @@ You should start the microservices in any other. Example

```bash

# Generate protobuf typescript definitions and please fix the path for timestamps import (You should do this only when you update the protobuf files)
# Generate protobuf typescript definitions and please fix the path for timestamps import (You should do this only when you update the protobuf files)
# and also build the proto-scheme lib (You should do this only when you update the protobuf files)
# in `lib/proto-schem`
$ sh ./gen-ts.sh

# Now build the proto-scheme lib (You should do this only when you update the protobuf files)
$ nest build proto-schema
$ yarn setup:local

# Start the account service
$ npx nest start service-account
Expand Down
45 changes: 23 additions & 22 deletions apps/api-admin/config.example
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
app:
port: 9900
caching:
ttl: 5
max: 1000
auth:
facebook:
clientID: 'gfgfggfgfgfgf'
clientSecret: 'fgfgfgfgf'
fbGraphVersion: 'v3.0'
callbackURL: 'https://142fa311.ngrok.io/account/facebook/callback'
github:
clientID: 'gfgfgfgfgfgf'
clientSecret: 'gfgfgfgfgfgfgfg'
fbGraphVersion: 'v3.0'
callbackURL: 'https://142fa311.ngrok.io/account/github/callback'
google:
clientID: 'fgffgfgfg'
clientSecret: 'fgfgfgfgfggf'
fbGraphVersion: 'v3.0'
callbackURL: 'https://142fa311.ngrok.io/account/google/callback'
enableJwtAuth: false,
enableSessionAuth: false,
jwtSettings:
secret: "eyJhbGciOiJSUzI1NiIsImtpZCI6Im1hYXNfcHJvZF8yMDIwMDMyNiIsInR5cCI6IkpXVCJ9"

memcached:
uri: "localhost:11211"
retries: 10
retry: 1000

jwt:
secret: "final-acid-pro"
strategies:
facebook:
clientID: 'gfgfggfgfgfgf'
clientSecret: 'fgfgfgfgf'
fbGraphVersion: 'v3.0'
callbackURL: 'https://142fa311.ngrok.io/account/facebook/callback'
github:
clientID: 'gfgfgfgfgfgf'
clientSecret: 'gfgfgfgfgfgfgfg'
fbGraphVersion: 'v3.0'
callbackURL: 'https://142fa311.ngrok.io/account/github/callback'
google:
clientID: 'fgffgfgfg'
clientSecret: 'fgfgfgfgfggf'
fbGraphVersion: 'v3.0'
callbackURL: 'https://142fa311.ngrok.io/account/google/callback'

database:
mongodb:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ describe('AccessTokenMutationResolver', () => {
providers: [AccessTokenMutationResolver],
}).compile();

resolver = module.get<AccessTokenMutationResolver>(AccessTokenMutationResolver);
resolver = module.get<AccessTokenMutationResolver>(
AccessTokenMutationResolver,
);
});

it('should be defined', () => {
Expand Down
64 changes: 50 additions & 14 deletions apps/api-admin/src/access-token/access-token-mutation.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,66 @@ import { Args, Context, ResolveField, Resolver } from '@nestjs/graphql';
import {
DeleteAccessTokenInput,
AccessToken,
AccessTokenMutations, CreateAccessTokenInput,
AccessTokenMutations,
CreateAccessTokenInput,
} from './types';
import { GqlContext, Resource, AccessTokenRpcClientService, setRpcContext, GqlAuthGuard } from '@ultimatebackend/core';
import {
GqlContext,
Resource,
setRpcContext,
GqlAuthGuard,
} from '@ultimatebackend/core';
import { UseGuards } from '@nestjs/common';

@Resolver(() => AccessTokenMutations)
export class AccessTokenMutationResolver {
constructor(private readonly service: AccessTokenRpcClientService) {}

@Resource({ name: 'access_token', identify: 'access_token', roles: ['owner', 'admin'], action: 'delete' })
@UseGuards(GqlAuthGuard)
@Resource({
name: 'access_token',
identify: 'access_token',
roles: ['owner', 'admin'],
action: 'delete',
})
@ResolveField(() => AccessToken)
async delete(@Args('input') input: DeleteAccessTokenInput, @Context() ctx: GqlContext): Promise<AccessToken> {
const res = await this.service.accessToken.deleteAccess({ id: input.id }, setRpcContext(ctx)).toPromise();
return res.accessToken as AccessToken;
async delete(
@Args('input') input: DeleteAccessTokenInput,
@Context() ctx: GqlContext,
): Promise<AccessToken> {
const res = await ctx?.rpc?.accessToken?.svc
.deleteAccess(
{
id: input.id,
tenantId: input?.tenantId,
},
setRpcContext(ctx),
)
.toPromise();
return (res.accessToken as unknown) as AccessToken;
}

@Resource({ name: 'access_token', identify: 'access_token', roles: ['owner', 'admin'], action: 'create' })
@UseGuards(GqlAuthGuard)
@Resource({
name: 'access_token',
identify: 'access_token',
roles: ['owner', 'admin'],
action: 'create',
})
@ResolveField(() => AccessToken)
async create(@Args('input') input: CreateAccessTokenInput, @Context() ctx: GqlContext): Promise<AccessToken> {
const res = await this.service.accessToken.createAccess(
{ name: input.name, scopes: input.scopes, tenantId: null,
}, setRpcContext(ctx)).toPromise();
return res.accessToken as AccessToken;
async create(
@Args('input') input: CreateAccessTokenInput,
@Context() ctx: GqlContext,
): Promise<AccessToken> {
const res = await ctx?.rpc?.accessToken?.svc
.createAccess(
{
name: input.name,
scopes: input.scopes,
tenantId: input?.tenantId,
expireAt: input?.expireAt,
},
setRpcContext(ctx),
)
.toPromise();
return (res.accessToken as unknown) as AccessToken;
}
}
7 changes: 1 addition & 6 deletions apps/api-admin/src/access-token/access-token.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { Module } from '@nestjs/common';
import { AccessTokenResolver } from './access-token.resolver';
import { RolesRpcClientService } from '@ultimatebackend/core';
import { AccessTokenMutationResolver } from './access-token-mutation.resolver';

@Module({
providers: [
AccessTokenResolver,
AccessTokenMutationResolver,
RolesRpcClientService,
],
providers: [AccessTokenResolver, AccessTokenMutationResolver],
})
export class AccessTokenModule {}
83 changes: 65 additions & 18 deletions apps/api-admin/src/access-token/access-token.resolver.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,77 @@
import { Args, Context, Mutation, Query, Resolver } from '@nestjs/graphql';
import { AccessToken, AccessTokenMutations } from './types';
import { AccessTokenRpcClientService, GqlContext, Resource, setRpcContext } from '@ultimatebackend/core';
import {
AccessToken,
AccessTokenFilterArgs,
AccessTokenMutations,
ReadAccessTokenInput,
} from './types';
import {
GqlAuthGuard,
GqlContext,
Resource,
setRpcContext,
} from '@ultimatebackend/core';
import { UseGuards } from '@nestjs/common';

@Resolver(() => AccessToken)
export class AccessTokenResolver {
constructor(private readonly service: AccessTokenRpcClientService) {}

@Resource({ name: 'access_token', identify: 'access_token', roles: ['owner', 'admin', 'developer'], action: 'read' })
@Query(() => [AccessToken])
@UseGuards(GqlAuthGuard)
@Resource({
name: 'access_token',
identify: 'access_token',
roles: ['owner', 'admin', 'developer'],
action: 'read',
})
@Query(() => [AccessToken], { nullable: true })
async accessTokens(
@Context() ctx: GqlContext): Promise<AccessToken[]> {
const res = await this.service.accessToken.findAccess({ id: null, tenantId: null }, setRpcContext(ctx)).toPromise();
return res.accessToken as AccessToken[];
@Args() input: AccessTokenFilterArgs,
@Context() ctx: GqlContext,
): Promise<AccessToken[]> {
let t;
let r;
if (input?.where) {
const { tenantId, ...rest } = input?.where;
t = tenantId;
r = rest;
}

const res = await ctx?.rpc?.accessToken?.svc
.findAccess(
{
filter: JSON.stringify(r),
tenantId: t,
},
setRpcContext(ctx),
)
.toPromise();
return (res.accessToken as unknown) as AccessToken[];
}

@Resource({ name: 'access_token', identify: 'access_token', roles: ['owner', 'admin', 'developer'], action: 'read' })
@Query(() => AccessToken)
async accessToken(@Args('id') id: string, @Context() ctx: GqlContext): Promise<AccessToken> {
const res = await this.service.accessToken.readAccess(
{
id, tenantId: null,
}, setRpcContext(ctx)).toPromise();
return res.accessToken as AccessToken;
@UseGuards(GqlAuthGuard)
@Resource({
name: 'access_token',
identify: 'access_token',
roles: ['owner', 'admin', 'developer'],
action: 'read',
})
@Query(() => AccessToken, { nullable: true })
async accessToken(
@Args('input') input: ReadAccessTokenInput,
@Context() ctx: GqlContext,
): Promise<AccessToken> {
const res = await ctx?.rpc?.accessToken?.svc
.readAccess(
{
id: input?.id,
tenantId: input?.tenantId,
},
setRpcContext(ctx),
)
.toPromise();
return (res.accessToken as unknown) as AccessToken;
}

@Mutation(() => AccessTokenMutations, {nullable: true, name: 'accessToken'})
@Mutation(() => AccessTokenMutations, { nullable: true, name: 'accessToken' })
async accessTokenMutation() {
return {};
}
Expand Down
21 changes: 18 additions & 3 deletions apps/api-admin/src/access-token/types/access-token.input.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
import { InputType, ArgsType, Field, ID } from '@nestjs/graphql';
import { FilterMongo, PaginationInput } from '@ultimatebackend/contracts';
import { AccessToken } from './access-token.type';
import { WithTenantInput } from '../../common';

@InputType()
export class CreateAccessTokenInput {
export class CreateAccessTokenInput extends WithTenantInput {
@Field()
name: string;

@Field(() => [String], { nullable: true })
scopes?: string[];

@Field({ nullable: true })
expireAt: string;
}

@InputType()
export class DeleteAccessTokenInput {
export class DeleteAccessTokenInput extends WithTenantInput {
@Field(() => ID)
id: string;
}

@InputType()
export class AccessTokenFilterInput extends FilterMongo(AccessToken, { simple: true }) {}
export class AccessTokenFilterInput extends FilterMongo(AccessToken, {
simple: true,
}) {
@Field({ nullable: true })
tenantId: string;
}

@ArgsType()
export class AccessTokenFilterArgs {
Expand All @@ -28,3 +37,9 @@ export class AccessTokenFilterArgs {
@Field(() => PaginationInput, { nullable: true })
paginate?: PaginationInput;
}

@InputType()
export class ReadAccessTokenInput extends WithTenantInput {
@Field(() => ID)
id: string;
}
7 changes: 4 additions & 3 deletions apps/api-admin/src/access-token/types/access-token.type.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import { ObjectType, Directive, Field } from '@nestjs/graphql';
import { Node } from '@ultimatebackend/contracts';
import { Node } from '@ultimatebackend/contracts';
import { Filterable } from '@ultimatebackend/core';

@Directive(`@key(fields: "id")`)
@ObjectType()
export class AccessToken extends Node {

@Field(() => [String])
scopes: string[];

@Field()
token: string;

@Filterable()
@Field({ nullable: true })
active: boolean;

@Filterable()
@Field({ nullable: true })
name: string;

@Field({ nullable: true })
expireAt: string;
}

@ObjectType()
Expand Down
Loading

0 comments on commit 31850cc

Please sign in to comment.