-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
25 changed files
with
392 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@octopost/types": patch | ||
--- | ||
|
||
first types |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Express from 'express'; | ||
import setupRoutes from './routes'; | ||
import setupMiddlewares from './middlewares'; | ||
|
||
const app = Express(); | ||
|
||
setupRoutes(app); | ||
setupMiddlewares(app); | ||
|
||
export default app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import dotenv from 'dotenv'; | ||
|
||
if (process.env['MODE'] === 'DEV') { | ||
dotenv.config({ | ||
path: ['dev.env', '.env'], | ||
}); | ||
} | ||
|
||
if (process.env['MODE'] === 'PROD') { | ||
dotenv.config({ | ||
path: ['prod.env', '.env'], | ||
}); | ||
} | ||
|
||
if (process.env['MODE'] === 'QA') { | ||
dotenv.config({ | ||
path: ['qa.env', '.env'], | ||
}); | ||
} | ||
|
||
export default { | ||
PORT: process.env['PORT'], | ||
HOSTNAME: process.env['HOSTNAME'], | ||
OAUTH_MASTODON_CLIENT_SECRET: process.env['OAUTH_MASTODON_CLIENT_SECRET'], | ||
OAUTH_MASTODON_CLIENT_ID: process.env['OAUTH_MASTODON_CLIENT_ID'], | ||
} as Record<string, string>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { Express } from 'express'; | ||
import { cors } from '@/middlewares/cors'; | ||
import { bodyParser } from '@/middlewares/body-parser'; | ||
|
||
export default function setupMiddlewares(app: Express): void { | ||
app.use(bodyParser); | ||
app.use(cors); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { Express } from 'express'; | ||
import { glob } from 'glob'; | ||
import { resolve } from 'node:path'; | ||
|
||
export default function setupRoutes(app: Express) { | ||
const routes = glob.sync([ | ||
resolve(import.meta.dirname, '../features/**/v1/*-routes.ts'), | ||
]); | ||
|
||
// eslint-disable-next-line @typescript-eslint/no-floating-promises | ||
routes.map(async (file) => { | ||
const { router, prefix } = (await import(file)).default; | ||
app.use(`/v1/${prefix}`, router); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import type { HttpClient } from '@/shared/protocols/http-client'; | ||
|
||
interface GetAuthorizationURLParams { | ||
responseType: string; | ||
clientId: string; | ||
redirectUri?: string; | ||
instance: string; | ||
scopes: string[]; | ||
} | ||
|
||
interface GetTokenParams { | ||
grantType: string; | ||
code: string; | ||
clientId: string; | ||
redirectUri?: string; | ||
instance: string; | ||
scopes: string[]; | ||
} | ||
|
||
interface GetTokenResponse { | ||
access_token: string; | ||
token_type: string; | ||
scope: string; | ||
created_at: number; | ||
} | ||
|
||
export class MastodonApi { | ||
private readonly scopes: string[] = ['read', 'write']; | ||
|
||
constructor(private readonly httpClient: HttpClient) {} | ||
|
||
getAuthorizationURL = ({ | ||
responseType, | ||
clientId, | ||
instance, | ||
redirectUri = 'urn:ietf:wg:oauth:2.0:oob', | ||
scopes = this.scopes, | ||
}: GetAuthorizationURLParams) => { | ||
const url = new URL('/oauth/authorize', instance); | ||
const searchParams = url.searchParams; | ||
|
||
searchParams.append('client_id', clientId); | ||
searchParams.append('redirect_uri', redirectUri); | ||
searchParams.append('response_type', responseType); | ||
searchParams.append('scope', scopes.join('+')); | ||
|
||
return url.href; | ||
}; | ||
|
||
getToken = async ({ | ||
grantType, | ||
code, | ||
clientId, | ||
redirectUri = 'urn:ietf:wg:oauth:2.0:oob', | ||
instance, | ||
scopes = this.scopes, | ||
}: GetTokenParams) => { | ||
const form = new FormData(); | ||
const url = new URL('/oauth/token', instance); | ||
|
||
form.append('grant_type', grantType); | ||
form.append('code', code); | ||
form.append('client_id', clientId); | ||
form.append('redirect_uri', redirectUri); | ||
form.append('scope', scopes.join(',')); | ||
|
||
const response = await this.httpClient.request<GetTokenResponse>({ | ||
method: 'post', | ||
body: form, | ||
url: url.href, | ||
}); | ||
|
||
return response; | ||
}; | ||
} |
21 changes: 21 additions & 0 deletions
21
src/features/mastodon/infra/http/controller/v1/mastodon-controller.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import type { HttpError } from '@/shared/errors/HttpError'; | ||
import { | ||
responseErrorFactory, | ||
responseOkFactory, | ||
} from '@/shared/factories/responses'; | ||
import type { Controller } from '@/shared/protocols/controller'; | ||
import type { HttpRequest } from '@/shared/protocols/http'; | ||
import type { Service } from '@/shared/protocols/service'; | ||
|
||
export class MastodonController implements Controller { | ||
constructor(private mastodonServiceFindAll: Service<unknown>) {} | ||
|
||
findAll = async (httpRequest: HttpRequest) => { | ||
try { | ||
const response = await this.mastodonServiceFindAll.execute(httpRequest); | ||
return responseOkFactory(response); | ||
} catch (error) { | ||
return responseErrorFactory(error as HttpError); | ||
} | ||
}; | ||
} |
16 changes: 16 additions & 0 deletions
16
src/features/mastodon/infra/http/routes/v1/mastodon-controller-factory.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { MastodonAuthService } from '@/features/mastodon/services/v1/mastodon-auth-service'; | ||
import { MastodonController } from '@/features/mastodon/infra/http/controller/v1/mastodon-controller'; | ||
import { MastodonApi } from '@/features/mastodon/infra/api/mastodon-api'; | ||
import { AxiosHttpClient } from '@/shared/infra/http-client'; | ||
|
||
export function mastodonControllerFactory() { | ||
const axiosHttpClient = new AxiosHttpClient(); | ||
|
||
const mastodonApi = new MastodonApi(axiosHttpClient); | ||
|
||
const mastodonServiceFindAll = new MastodonAuthService(mastodonApi); | ||
|
||
const mastodonController = new MastodonController(mastodonServiceFindAll); | ||
|
||
return { mastodonController }; | ||
} |
21 changes: 21 additions & 0 deletions
21
src/features/mastodon/infra/http/routes/v1/mastodon-routes.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { Router } from 'express'; | ||
import { mastodonControllerFactory } from './mastodon-controller-factory'; | ||
import { redirectRouteAdapter } from '@/shared/adapters/redirect-router-adapter'; | ||
|
||
const router = Router(); | ||
|
||
const { mastodonController } = mastodonControllerFactory(); | ||
|
||
router.get('/authorize', redirectRouteAdapter(mastodonController.findAll)); | ||
|
||
router.get( | ||
'/callback', | ||
redirectRouteAdapter((payload) => | ||
Promise.resolve({ body: payload, statusCode: 301 }) | ||
) | ||
); | ||
|
||
export default { | ||
router, | ||
prefix: 'mastodon', | ||
}; |
30 changes: 30 additions & 0 deletions
30
src/features/mastodon/services/v1/mastodon-auth-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import type { | ||
MastodonAuthRequestBody, | ||
MastodonAuthRequestResponse, | ||
} from '@octopost/types'; | ||
|
||
import type { MastodonApi } from '@/features/mastodon/infra/api/mastodon-api'; | ||
import type { HttpRequest } from '@/shared/protocols/http'; | ||
import type { ServiceRedirect } from '@/shared/protocols/service'; | ||
import env from '@/config/env'; | ||
|
||
export class MastodonAuthService implements ServiceRedirect { | ||
constructor(private mastodonApi: MastodonApi) {} | ||
|
||
execute( | ||
httpRequest: HttpRequest<object, object, MastodonAuthRequestBody> | ||
): Promise<MastodonAuthRequestResponse> { | ||
const body = httpRequest.body!; | ||
|
||
body.instance = 'https://mastodon.social'; | ||
|
||
const authorizationUrl = this.mastodonApi.getAuthorizationURL({ | ||
instance: body.instance, | ||
clientId: env.OAUTH_MASTODON_CLIENT_ID, | ||
responseType: 'code', | ||
scopes: ['read', 'write'], | ||
}); | ||
|
||
return Promise.resolve(authorizationUrl); | ||
} | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
import http from 'node:http'; | ||
import env from './config/env'; | ||
import app from './config/app'; | ||
|
||
// Create a local server to receive data from | ||
const server = http.createServer((req, res) => { | ||
res.writeHead(200, { 'Content-Type': 'application/json' }); | ||
res.end( | ||
JSON.stringify({ | ||
data: 'Hello World!', | ||
}) | ||
); | ||
}); | ||
function startServer() { | ||
const listener = app.listen(Number(env.PORT), env.HOSTNAME, () => { | ||
console.log(`Server running at http://localhost:${env.PORT}`); | ||
}); | ||
|
||
server.listen(8000, () => { | ||
console.log('listening on port 8000'); | ||
}); | ||
listener.on('error', (err) => { | ||
console.error(err); | ||
process.exit(1); | ||
}); | ||
} | ||
|
||
startServer(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { json } from 'express'; | ||
|
||
export const bodyParser = json(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { Request, Response, NextFunction } from 'express'; | ||
|
||
export const cors = (req: Request, res: Response, next: NextFunction): void => { | ||
res.set('access-control-allow-origin', '*'); | ||
res.set('access-control-allow-headers', '*'); | ||
res.set('access-control-allow-methods', '*'); | ||
next(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* eslint-disable @typescript-eslint/no-misused-promises */ | ||
import type { RequestHandler } from 'express'; | ||
import type { HttpRequest, HttpResponse } from '../protocols/http'; | ||
|
||
type Method = (httpRequest: HttpRequest) => Promise<HttpResponse>; | ||
|
||
export function redirectRouteAdapter(method: Method): RequestHandler { | ||
return async (req, res) => { | ||
const httpRequest: HttpRequest = { | ||
body: req.body as object, | ||
pathParams: req.params as Record<string, string | number>, | ||
queryParams: req.query as Record<string, string | number>, | ||
}; | ||
|
||
const httpResponse = await method(httpRequest); | ||
|
||
if (httpResponse.statusCode !== 200) { | ||
return res.status(httpResponse.statusCode).json(httpResponse.body); | ||
} | ||
|
||
res.status(httpResponse.statusCode).redirect(httpResponse.body); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* eslint-disable @typescript-eslint/no-misused-promises */ | ||
import type { RequestHandler } from 'express'; | ||
import type { HttpRequest, HttpResponse } from '../protocols/http'; | ||
|
||
type Method = (httpRequest: HttpRequest) => Promise<HttpResponse>; | ||
|
||
export function routeAdapter(method: Method): RequestHandler { | ||
return async (req, res) => { | ||
const httpRequest: HttpRequest = { | ||
body: req.body as object, | ||
pathParams: req.params as Record<string, string | number>, | ||
queryParams: req.query as Record<string, string | number>, | ||
}; | ||
|
||
const httpResponse = await method(httpRequest); | ||
|
||
res.status(httpResponse.statusCode).json(httpResponse.body); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export class HttpError extends Error { | ||
constructor( | ||
public readonly code: number, | ||
message: string | ||
) { | ||
super(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import type { HttpError } from '../errors/HttpError'; | ||
import type { HttpResponse } from '../protocols/http'; | ||
|
||
export const responseErrorFactory = (error: HttpError): HttpResponse => ({ | ||
statusCode: 500, | ||
body: { statusCode: 500, message: error.message }, | ||
}); | ||
|
||
export const responseOkFactory = (body: unknown): HttpResponse => ({ | ||
statusCode: 200, | ||
body, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import axios from 'axios'; | ||
import type { AxiosError } from 'axios'; | ||
import type { | ||
HttpClient, | ||
HttpClientRequest, | ||
HttpClientResponse, | ||
} from '../protocols/http-client'; | ||
|
||
export class AxiosHttpClient implements HttpClient { | ||
async request(data: HttpClientRequest): Promise<HttpClientResponse> { | ||
try { | ||
const response = await axios({ | ||
url: data.url, | ||
method: data.method, | ||
data: data.body, | ||
headers: data.headers, | ||
}); | ||
|
||
return { | ||
statusCode: response.status, | ||
body: response.data, | ||
}; | ||
} catch (error) { | ||
return { | ||
statusCode: (error as AxiosError).response!.status, | ||
body: (error as AxiosError).response!.data, | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export interface Controller {} |
Oops, something went wrong.