@things-factory/oauth2-client 8.0.0 → 9.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,188 +0,0 @@
1
- import '@material/web/button/elevated-button.js'
2
- import '@material/web/button/outlined-button.js'
3
-
4
- import gql from 'graphql-tag'
5
- import { css, html } from 'lit'
6
- import { customElement, property } from 'lit/decorators.js'
7
- import { connect } from 'pwa-helpers/connect-mixin.js'
8
-
9
- import { client } from '@operato/graphql'
10
- import { notify } from '@operato/layout'
11
- import { navigate, PageView, store } from '@operato/shell'
12
-
13
- @customElement('oauth2-clients')
14
- class Oauth2Clients extends connect(store)(PageView) {
15
- static styles = [
16
- css`
17
- :host {
18
- display: flex;
19
- flex-direction: column;
20
- background-color: var(--md-sys-color-background);
21
- padding: var(--spacing-large);
22
-
23
- overflow: auto;
24
- }
25
-
26
- md-elevated-button {
27
- text-transform: capitalize;
28
- }
29
-
30
- md-outlined-button {
31
- float: right;
32
- margin-top: var(--spacing-medium);
33
- text-transform: capitalize;
34
- }
35
-
36
- h2 {
37
- margin: var(--title-margin);
38
- font: var(--title-font);
39
- color: var(--title-text-color);
40
- }
41
-
42
- [page-description] {
43
- margin: var(--page-description-margin);
44
- font: var(--page-description-font);
45
- color: var(--page-description-color);
46
- }
47
-
48
- table {
49
- width: 100%;
50
- margin: var(--spacing-large) 0;
51
- border-collapse: collapse;
52
- }
53
-
54
- tr {
55
- background-color: var(--tr-background-color);
56
- }
57
-
58
- tr:nth-child(odd) {
59
- background-color: var(--tr-background-odd-color);
60
- }
61
-
62
- tr:hover {
63
- background-color: var(--tr-background-hover-color);
64
- }
65
-
66
- th {
67
- border-top: var(--th-border-top);
68
- border-bottom: var(--td-border-bottom);
69
- padding: var(--th-padding);
70
-
71
- font: var(--th-font);
72
- color: var(--th-color);
73
- text-transform: var(--th-text-transform);
74
- text-align: left;
75
- }
76
-
77
- td {
78
- padding: var(--td-padding);
79
- border-bottom: var(--border-dim-color);
80
- line-height: 1.1;
81
- }
82
-
83
- td a {
84
- font: var(--td-font);
85
- text-decoration: none;
86
- color: var(--md-sys-color-on-surface);
87
- }
88
-
89
- td a strong {
90
- font: bold 16px var(--theme-font);
91
-
92
- display: block;
93
- text-decoration: none;
94
- }
95
-
96
- .text-align-center {
97
- text-align: center;
98
- }
99
-
100
- .text-align-right {
101
- text-align: right;
102
- }
103
- `
104
- ]
105
-
106
- @property({ type: Array }) clients: any[] = []
107
-
108
- get context() {
109
- return {
110
- title: `clients`
111
- }
112
- }
113
-
114
- render() {
115
- var clients = this.clients || []
116
-
117
- return html`
118
- <div>
119
- <h2>Registered Oauth2 Clients</h2>
120
- <p page-description>
121
- What type of oauth2 client are you building?<br />Choose the platform type that best suits the audience you’re
122
- building for.
123
- </p>
124
- <md-elevated-button @click=${e => navigate('oauth2-client-register')}
125
- >register new oauth2 client</md-elevated-button
126
- >
127
- </div>
128
-
129
- <div>
130
- <table>
131
- <tr>
132
- <th>app name</th>
133
- <th>API health</th>
134
- <th>Installs</th>
135
- <th>status</th>
136
- </tr>
137
- ${clients.map(
138
- client => html`
139
- <tr>
140
- <td>
141
- <a href=${`oauth2-client/${client.id}`}>
142
- <strong>${client.name}</strong>
143
- ${client.description}
144
- </a>
145
- </td>
146
- <td class="text-align-center">OK</td>
147
- <td class="text-align-right">1</td>
148
- <td class="text-align-center">draft</td>
149
- </tr>
150
- `
151
- )}
152
- </table>
153
- </div>
154
- `
155
- }
156
-
157
- async pageUpdated(changes, lifecycle, before) {
158
- if (this.active) {
159
- this.clients = (await this.fetchOauth2Clients())?.items || []
160
- }
161
- }
162
-
163
- async fetchOauth2Clients() {
164
- const response = await client.query({
165
- query: gql`
166
- query {
167
- oauth2Clients {
168
- items {
169
- id
170
- name
171
- description
172
- }
173
- total
174
- }
175
- }
176
- `
177
- })
178
-
179
- if (response.errors) {
180
- notify({
181
- level: 'error',
182
- message: 'fetch oauth2 clients fail'
183
- })
184
- } else {
185
- return response.data.oauth2Clients
186
- }
187
- }
188
- }
package/client/route.ts DELETED
@@ -1,15 +0,0 @@
1
- export default function route(page: string) {
2
- switch (page) {
3
- case 'oauth2-client-register':
4
- import('./pages/oauth2-client-register')
5
- return page
6
-
7
- case 'oauth2-client':
8
- import('./pages/oauth2-client')
9
- return page
10
-
11
- case 'oauth2-clients':
12
- import('./pages/oauth2-clients')
13
- return page
14
- }
15
- }
@@ -1,13 +0,0 @@
1
- {
2
- "extends": "../../tsconfig-base.json",
3
- "compilerOptions": {
4
- "experimentalDecorators": true,
5
- "skipLibCheck": true,
6
- "strict": true,
7
- "declaration": true,
8
- "module": "esnext",
9
- "outDir": "../dist-client",
10
- "baseUrl": "./"
11
- },
12
- "include": ["./**/*"]
13
- }
package/server/index.ts DELETED
@@ -1,3 +0,0 @@
1
- import './routes'
2
-
3
- export * from './service'
package/server/routes.ts DELETED
@@ -1,156 +0,0 @@
1
- import ClientOAuth2 from 'client-oauth2'
2
- import crypto from 'crypto'
3
-
4
- import { getRedirectSubdomainPath, getRepository } from '@things-factory/shell'
5
-
6
- import { Oauth2Client } from './service/oauth2-client/oauth2-client'
7
-
8
- process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRouter) => {
9
- domainPrivateRouter.get('/oauth2-client/:id/auth-uri', async (context, next) => {
10
- const { params, origin } = context
11
- const { id } = params
12
-
13
- const repository = getRepository(Oauth2Client)
14
- const oauth2Client = await repository.findOneBy({ id })
15
-
16
- const {
17
- grantType,
18
- clientId,
19
- clientSecret,
20
- accessTokenUrl: accessTokenUri,
21
- authUrl: authorizationUri,
22
- scopes
23
- } = oauth2Client
24
-
25
- if (grantType !== 'code') {
26
- throw new Error(`unsupported grant type: ${grantType}`)
27
- }
28
-
29
- const state = crypto.randomBytes(16).toString('hex')
30
- await repository.save({
31
- ...oauth2Client,
32
- state
33
- })
34
-
35
- var auth = new ClientOAuth2({
36
- clientId,
37
- clientSecret,
38
- accessTokenUri,
39
- authorizationUri,
40
- redirectUri: `${origin}/oauth2-client/callback`,
41
- scopes: scopes?.split(' ') || [],
42
- state
43
- })
44
-
45
- context.status = 200
46
- context.body = await auth.code.getUri()
47
- })
48
-
49
- domainPrivateRouter.get('/oauth2-client/:id/refresh', async (context, next) => {
50
- const { params } = context
51
- const { id } = params
52
-
53
- const repository = getRepository(Oauth2Client)
54
- const oauth2Client = await repository.findOneBy({ id })
55
-
56
- const {
57
- grantType,
58
- clientId,
59
- clientSecret,
60
- accessTokenUrl: accessTokenUri,
61
- authUrl: authorizationUri,
62
- scopes,
63
- tokenType,
64
- accessToken,
65
- refreshToken
66
- } = oauth2Client
67
-
68
- if (!refreshToken) {
69
- context.status = 404
70
- context.body = 'refreshToken not found'
71
-
72
- return
73
- }
74
-
75
- var auth = new ClientOAuth2({
76
- clientId,
77
- clientSecret,
78
- accessTokenUri,
79
- authorizationUri,
80
- scopes: scopes?.split(' ') || []
81
- })
82
-
83
- const { accessToken: newAccessToken, refreshToken: newRefreshToken } = await auth
84
- .createToken(accessToken, refreshToken, tokenType, {})
85
- .refresh()
86
-
87
- context.status = 200
88
- context.body = await repository.save({
89
- ...oauth2Client,
90
- accessToken: newAccessToken,
91
- refreshToken: newRefreshToken,
92
- state: ''
93
- })
94
- })
95
- })
96
-
97
- process.on('bootstrap-module-domain-public-route' as any, (app, domainPublicRouter) => {
98
- domainPublicRouter.get('/oauth2-client/callback', async (context, next) => {
99
- const { state } = context.query
100
- const { originalUrl } = context
101
-
102
- const repository = getRepository(Oauth2Client)
103
- const oauth2Client: Oauth2Client = await repository.findOne({
104
- where: { state },
105
- relations: ['domain']
106
- })
107
-
108
- const {
109
- domain,
110
- id,
111
- grantType,
112
- clientId,
113
- clientSecret,
114
- accessTokenUrl: accessTokenUri,
115
- authUrl: authorizationUri,
116
- scopes
117
- } = oauth2Client
118
-
119
- var auth = new ClientOAuth2({
120
- clientId,
121
- clientSecret,
122
- accessTokenUri,
123
- authorizationUri,
124
- scopes: scopes?.split(' ') || []
125
- })
126
-
127
- var url = originalUrl
128
- switch (grantType) {
129
- case 'credentials':
130
- break
131
- case 'jwt':
132
- break
133
- case 'code':
134
- break
135
- case 'owner':
136
- default:
137
- throw new Error(`unsupported grant type: ${grantType}`)
138
- }
139
-
140
- const token = await auth.code.getToken(originalUrl)
141
- const { tokenType, accessToken, refreshToken, data } = token
142
- const expires = data?.expires_in ? token.expiresIn(data?.expires_in as any) : null
143
-
144
- await repository.save({
145
- ...oauth2Client,
146
- tokenType,
147
- accessToken,
148
- refreshToken,
149
- expires,
150
- scopes: data?.scope?.replace(',', ' '),
151
- state: ''
152
- })
153
-
154
- context.redirect(getRedirectSubdomainPath(context, domain?.subdomain, `/oauth2-client/${id}`))
155
- })
156
- })
@@ -1,17 +0,0 @@
1
- /* IMPORT ENTITIES AND RESOLVERS */
2
- import { entities as Oauth2ClientEntities, resolvers as Oauth2ClientResolvers } from './oauth2-client'
3
-
4
- /* EXPORT ENTITY TYPES */
5
- export * from './oauth2-client/oauth2-client'
6
-
7
- export const entities = [
8
- /* ENTITIES */
9
- ...Oauth2ClientEntities
10
- ]
11
-
12
- export const schema = {
13
- resolverClasses: [
14
- /* RESOLVER CLASSES */
15
- ...Oauth2ClientResolvers
16
- ]
17
- }
@@ -1,6 +0,0 @@
1
- import { Oauth2Client } from './oauth2-client'
2
- import { Oauth2ClientQuery } from './oauth2-client-query'
3
- import { Oauth2ClientMutation } from './oauth2-client-mutation'
4
-
5
- export const entities = [Oauth2Client]
6
- export const resolvers = [Oauth2ClientQuery, Oauth2ClientMutation]
@@ -1,202 +0,0 @@
1
- import ClientOAuth2 from 'client-oauth2'
2
- import crypto from 'crypto'
3
- import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
4
- import { In } from 'typeorm'
5
-
6
- import { config } from '@things-factory/env'
7
-
8
- import { Oauth2Client } from './oauth2-client'
9
- import { NewOauth2Client, Oauth2ClientPatch } from './oauth2-client-type'
10
-
11
- const protocol: string = config.get('protocol')
12
-
13
- @Resolver(Oauth2Client)
14
- export class Oauth2ClientMutation {
15
- @Directive('@transaction')
16
- @Mutation(returns => Oauth2Client, { description: 'To create new Oauth2Client' })
17
- async createOauth2Client(
18
- @Arg('oauth2Client') oauth2Client: NewOauth2Client,
19
- @Ctx() context: ResolverContext
20
- ): Promise<Oauth2Client> {
21
- const { domain, user, tx } = context.state
22
-
23
- const originalProtocol = context.headers['x-forwarded-proto']
24
- const originalHost = context.headers['x-forwarded-host']
25
- const originalPort = context.headers['x-forwarded-port']
26
-
27
- if (originalProtocol && originalHost) {
28
- var url: URL = new URL(`${originalProtocol}://${originalHost}`)
29
- if (originalPort) {
30
- url.port = originalPort
31
- }
32
- } else {
33
- var url: URL = new URL(context.request.origin)
34
- }
35
-
36
- if (protocol) {
37
- url.protocol = protocol
38
- }
39
-
40
- url.pathname = '/oauth2-client/callback'
41
-
42
- return await tx.getRepository(Oauth2Client).save({
43
- ...oauth2Client,
44
- callbackUrl: oauth2Client.callbackUrl || url.href,
45
- domain,
46
- creator: user,
47
- updater: user
48
- })
49
- }
50
-
51
- @Directive('@transaction')
52
- @Mutation(returns => Oauth2Client, { description: 'To modify Oauth2Client information' })
53
- async updateOauth2Client(
54
- @Arg('id') id: string,
55
- @Arg('patch') patch: Oauth2ClientPatch,
56
- @Ctx() context: ResolverContext
57
- ): Promise<Oauth2Client> {
58
- const { domain, user, tx } = context.state
59
-
60
- const repository = tx.getRepository(Oauth2Client)
61
- const oauth2Client = await repository.findOne({
62
- where: { domain: { id: domain.id }, id }
63
- })
64
-
65
- return await repository.save({
66
- ...oauth2Client,
67
- ...patch,
68
- updater: user
69
- })
70
- }
71
-
72
- @Directive('@transaction')
73
- @Mutation(returns => Boolean, { description: 'To delete Oauth2Client' })
74
- async deleteOauth2Client(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
75
- const { domain, tx } = context.state
76
-
77
- await tx.getRepository(Oauth2Client).delete({ domain: { id: domain.id }, id })
78
-
79
- return true
80
- }
81
-
82
- @Directive('@transaction')
83
- @Mutation(returns => Boolean, { description: 'To delete multiple Oauth2Clients' })
84
- async deleteOauth2Clients(
85
- @Arg('ids', type => [String]) ids: string[],
86
- @Ctx() context: ResolverContext
87
- ): Promise<boolean> {
88
- const { domain, tx } = context.state
89
-
90
- await tx.getRepository(Oauth2Client).delete({
91
- domain: { id: domain.id },
92
- id: In(ids)
93
- })
94
-
95
- return true
96
- }
97
-
98
- @Directive('@transaction')
99
- @Mutation(returns => Boolean, { description: 'To import multiple Oauth2Clients' })
100
- async importOauth2Clients(
101
- @Arg('oauth2Clients', type => [Oauth2ClientPatch]) oauth2Clients: Oauth2ClientPatch[],
102
- @Ctx() context: ResolverContext
103
- ): Promise<boolean> {
104
- const { domain, tx } = context.state
105
-
106
- await Promise.all(
107
- oauth2Clients.map(async (oauth2Client: Oauth2ClientPatch) => {
108
- const createdOauth2Client: Oauth2Client = await tx.getRepository(Oauth2Client).save({ domain, ...oauth2Client })
109
- })
110
- )
111
-
112
- return true
113
- }
114
-
115
- @Directive('@transaction')
116
- @Mutation(returns => String, { description: 'To get oauth2 auth URL' })
117
- async getOauth2AuthUrl(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<string> {
118
- const { tx } = context.state
119
- const repository = tx.getRepository(Oauth2Client)
120
- const oauth2Client = await repository.findOneBy({ id })
121
-
122
- const {
123
- grantType,
124
- clientId,
125
- clientSecret,
126
- callbackUrl,
127
- accessTokenUrl: accessTokenUri,
128
- authUrl: authorizationUri,
129
- scopes
130
- } = oauth2Client
131
-
132
- if (grantType !== 'code') {
133
- throw new Error(`unsupported grant type: ${grantType}`)
134
- }
135
-
136
- const state = crypto.randomBytes(16).toString('hex')
137
- await repository.save({
138
- ...oauth2Client,
139
- state
140
- })
141
-
142
- var auth = new ClientOAuth2({
143
- clientId,
144
- clientSecret,
145
- accessTokenUri,
146
- authorizationUri,
147
- redirectUri: callbackUrl || `${context.origin}/oauth2-client/callback`,
148
- scopes: scopes?.split(' ') || [],
149
- state
150
- })
151
-
152
- return await (auth[grantType] as any).getUri()
153
- }
154
-
155
- @Directive('@transaction')
156
- @Mutation(returns => Oauth2Client, { description: 'To refresh oauth2 access token' })
157
- async refreshOauth2AccessToken(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Oauth2Client> {
158
- const { tx } = context.state
159
- const repository = tx.getRepository(Oauth2Client)
160
- const oauth2Client = await repository.findOneBy({ id })
161
-
162
- const {
163
- clientId,
164
- clientSecret,
165
- accessTokenUrl: accessTokenUri,
166
- authUrl: authorizationUri,
167
- scopes,
168
- tokenType,
169
- accessToken,
170
- refreshToken
171
- } = oauth2Client
172
-
173
- if (!refreshToken) {
174
- throw new Error('refreshToken not found')
175
- }
176
-
177
- var auth = new ClientOAuth2({
178
- clientId,
179
- clientSecret,
180
- accessTokenUri,
181
- authorizationUri,
182
- scopes: scopes?.split(' ')
183
- })
184
-
185
- try {
186
- var token = await auth.createToken(accessToken, refreshToken, tokenType, {}).refresh()
187
- } catch (err) {
188
- throw err
189
- }
190
-
191
- const { accessToken: newAccessToken, refreshToken: newRefreshToken, tokenType: newTokenType, data } = token
192
- const expires = data?.expires_in ? token.expiresIn(data?.expires_in as any) : null
193
-
194
- return await repository.save({
195
- ...oauth2Client,
196
- accessToken: newAccessToken,
197
- refreshToken: newRefreshToken,
198
- tokenType: newTokenType,
199
- expires
200
- })
201
- }
202
- }
@@ -1,53 +0,0 @@
1
- import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
2
-
3
- import { User } from '@things-factory/auth-base'
4
- import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
5
-
6
- import { Oauth2Client } from './oauth2-client'
7
- import { Oauth2ClientList } from './oauth2-client-type'
8
-
9
- @Resolver(Oauth2Client)
10
- export class Oauth2ClientQuery {
11
- @Query(returns => Oauth2Client!, { nullable: true, description: 'To fetch a Oauth2Client' })
12
- async oauth2Client(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Oauth2Client> {
13
- const { domain } = context.state
14
-
15
- return await getRepository(Oauth2Client).findOne({
16
- where: { domain: { id: domain.id }, id }
17
- })
18
- }
19
-
20
- @Query(returns => Oauth2ClientList, { description: 'To fetch multiple Oauth2Clients' })
21
- async oauth2Clients(
22
- @Args(type => ListParam) params: ListParam,
23
- @Ctx() context: ResolverContext
24
- ): Promise<Oauth2ClientList> {
25
- const { domain } = context.state
26
-
27
- const queryBuilder = getQueryBuilderFromListParams({
28
- domain,
29
- params,
30
- repository: await getRepository(Oauth2Client),
31
- searchables: ['name', 'description']
32
- })
33
-
34
- const [items, total] = await queryBuilder.getManyAndCount()
35
-
36
- return { items, total }
37
- }
38
-
39
- @FieldResolver(type => Domain)
40
- async domain(@Root() oauth2Client: Oauth2Client): Promise<Domain> {
41
- return await getRepository(Domain).findOneBy({ id: oauth2Client.domainId })
42
- }
43
-
44
- @FieldResolver(type => User)
45
- async updater(@Root() oauth2Client: Oauth2Client): Promise<User> {
46
- return await getRepository(User).findOneBy({ id: oauth2Client.updaterId })
47
- }
48
-
49
- @FieldResolver(type => User)
50
- async creator(@Root() oauth2Client: Oauth2Client): Promise<User> {
51
- return await getRepository(User).findOneBy({ id: oauth2Client.creatorId })
52
- }
53
- }