Skip to content

Commit

Permalink
using import_map.json instead of deps.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
sunjc committed Aug 14, 2021
1 parent d042a95 commit 75c649a
Show file tree
Hide file tree
Showing 28 changed files with 378 additions and 430 deletions.
27 changes: 13 additions & 14 deletions app.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import {bold, yellow} from "fmt/colors.ts";
import {Application} from "oak";
import {oakCors} from "cors";
import {
Application,
bold,
ConnectionOptions,
ConnectionOptionsReader,
createConnection,
oakCors,
yellow,
} from "./deps.ts";
ConnectionOptions,
ConnectionOptionsReader,
createConnection,
} from "typeorm";
import {config} from "./config/config.ts";
import router from "./routes.ts";
import {authorizationGuard, errorHandler, logger, notFound, oakSnelm, timing} from "./middleware/mod.ts";
Expand All @@ -15,7 +14,7 @@ import {authorizationGuard, errorHandler, logger, notFound, oakSnelm, timing} fr
* Reads connection options stored in ormconfig configuration file.
*/
async function getConnectionOptions(connectionName: string = "default"): Promise<ConnectionOptions> {
return new ConnectionOptionsReader({root: "."}).get(connectionName);
return new ConnectionOptionsReader({root: "."}).get(connectionName);
}

const {APP_HOST, APP_PORT, CORS_ORIGIN, CORS_METHODS, CORS_ALLOWED_HEADERS} = config;
Expand All @@ -25,9 +24,9 @@ const connectionOptions: ConnectionOptions = await getConnectionOptions();
await createConnection(connectionOptions);

const cors = oakCors({
origin: CORS_ORIGIN,
methods: CORS_METHODS,
allowedHeaders: CORS_ALLOWED_HEADERS
origin: CORS_ORIGIN,
methods: CORS_METHODS,
allowedHeaders: CORS_ALLOWED_HEADERS
});

const app = new Application();
Expand All @@ -44,11 +43,11 @@ app.use(router.allowedMethods());
app.use(notFound);

app.addEventListener("listen", ({hostname, port}) => {
console.log(bold("Start listening on ") + yellow(`${hostname}:${port}`));
console.log(bold("Start listening on ") + yellow(`${hostname}:${port}`));
});

if (import.meta.main) {
await app.listen(`${APP_HOST}:${APP_PORT}`);
await app.listen(`${APP_HOST}:${APP_PORT}`);
}

export {app};
126 changes: 63 additions & 63 deletions app_test.ts
Original file line number Diff line number Diff line change
@@ -1,106 +1,106 @@
import {superoak} from "./deps.ts";
import {superoak} from "superoak";
import {app} from "./app.ts";
import {makeAccessToken} from "./util/jwt.ts";
import {User} from "./entity/user.ts";
import {Authority, AuthorityName} from "./entity/authority.ts";

async function generateAdminToken() {
const user = new User();
user.username = "admin";
user.email = "[email protected]";
const user = new User();
user.username = "admin";
user.email = "[email protected]";

const roleAdmin = new Authority();
roleAdmin.name = AuthorityName.ADMIN;
const roleUser = new Authority();
const roleAdmin = new Authority();
roleAdmin.name = AuthorityName.ADMIN;
const roleUser = new Authority();

user.authorities = [roleAdmin, roleUser];
user.authorities = [roleAdmin, roleUser];

return await makeAccessToken(user);
return await makeAccessToken(user);
}

async function generateUserToken() {
const user = new User();
user.username = "user";
user.email = "[email protected]";
const user = new User();
user.username = "user";
user.email = "[email protected]";

const roleUser = new Authority();
const roleUser = new Authority();

user.authorities = [roleUser];
user.authorities = [roleUser];

return await makeAccessToken(user);
return await makeAccessToken(user);
}

const adminToken = await generateAdminToken();
const userToken = await generateUserToken();

Deno.test("Unauthorized Error", async () => {
const request = await superoak(app);
await request.get("/api/heroes").expect(401);
const request = await superoak(app);
await request.get("/api/heroes").expect(401);
});

Deno.test("Forbidden Error", async () => {
const request = await superoak(app);
await request.post("/api/heroes").auth(userToken, {type: "bearer"}).send({name: "Jack"})
.expect(403);
const request = await superoak(app);
await request.post("/api/heroes").auth(userToken, {type: "bearer"}).send({name: "Jack"})
.expect(403);
});

Deno.test("should get token successfully", async () => {
const request = await superoak(app);
await request.post("/api/auth").send({username: "admin", password: "admin"})
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(/{"token":.*,"refresh_token":.*}/i);
const request = await superoak(app);
await request.post("/api/auth").send({username: "admin", password: "admin"})
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(/{"token":.*,"refresh_token":.*}/i);
});

Deno.test("should provide correct credential", async () => {
const request = await superoak(app);
await request.post("/api/auth").send({username: "admin", password: "111111"})
.expect(401);
const request = await superoak(app);
await request.post("/api/auth").send({username: "admin", password: "111111"})
.expect(401);
});

Deno.test("crud should be executed successfully", async () => {
// add hero
let request = await superoak(app);
await request.post("/api/heroes").auth(adminToken, {type: "bearer"}).send({name: "Jack"})
.expect(200).expect(/{"name":"Jack","id":11,.*}/);

// update hero
request = await superoak(app);
await request.post("/api/heroes").auth(adminToken, {type: "bearer"}).send({name: "Jacky", id: 11})
.expect(200).expect(/{"name":"Jacky","id":11,.*}/);

// find heroes by name
request = await superoak(app);
await request.get("/api/heroes/?name=m").auth(adminToken, {type: "bearer"})
.expect(200);

// find heroes by page
request = await superoak(app);
await request.get("/api/heroes").auth(adminToken, {type: "bearer"}).send({page: 0, size: 10})
.expect(200).expect(/{.*"totalElements":11.*}/);

// get hero by id
request = await superoak(app);
await request.get("/api/heroes/11").auth(adminToken, {type: "bearer"})
.expect(200).expect(/{"id":11,"name":"Jacky",.*}/);

// delete hero
request = await superoak(app);
await request.delete("/api/heroes/11").auth(adminToken, {type: "bearer"}).expect(200);
// add hero
let request = await superoak(app);
await request.post("/api/heroes").auth(adminToken, {type: "bearer"}).send({name: "Jack"})
.expect(200).expect(/{"name":"Jack","id":11,.*}/);

// update hero
request = await superoak(app);
await request.post("/api/heroes").auth(adminToken, {type: "bearer"}).send({name: "Jacky", id: 11})
.expect(200).expect(/{"name":"Jacky","id":11,.*}/);

// find heroes by name
request = await superoak(app);
await request.get("/api/heroes/?name=m").auth(adminToken, {type: "bearer"})
.expect(200);

// find heroes by page
request = await superoak(app);
await request.get("/api/heroes").auth(adminToken, {type: "bearer"}).send({page: 0, size: 10})
.expect(200).expect(/{.*"totalElements":11.*}/);

// get hero by id
request = await superoak(app);
await request.get("/api/heroes/11").auth(adminToken, {type: "bearer"})
.expect(200).expect(/{"id":11,"name":"Jacky",.*}/);

// delete hero
request = await superoak(app);
await request.delete("/api/heroes/11").auth(adminToken, {type: "bearer"}).expect(200);
});

Deno.test("validation failed", async () => {
// add hero
const request = await superoak(app);
await request.post("/api/heroes").auth(adminToken, {type: "bearer"}).send({name: "J"})
.expect(400).expect(/.*,"message":"name characters length must be between 3-30; ",.*/i);
// add hero
const request = await superoak(app);
await request.post("/api/heroes").auth(adminToken, {type: "bearer"}).send({name: "J"})
.expect(400).expect(/.*,"message":"name characters length must be between 3-30; ",.*/i);
});

Deno.test("Path not found", async () => {
const request = await superoak(app);
await request.get("/api/test").auth(adminToken, {type: "bearer"}).expect(404);
const request = await superoak(app);
await request.get("/api/test").auth(adminToken, {type: "bearer"}).expect(404);
});

Deno.test("Entity not found", async () => {
const request = await superoak(app);
await request.get("/api/test/9999").auth(adminToken, {type: "bearer"}).expect(404);
const request = await superoak(app);
await request.get("/api/test/9999").auth(adminToken, {type: "bearer"}).expect(404);
});
4 changes: 2 additions & 2 deletions config/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import { config as loadConfig } from "../deps.ts";
import {config as loadConfig} from "dotenv";

export const config = loadConfig({ safe: true });
export const config = loadConfig({safe: true});
15 changes: 8 additions & 7 deletions controller/auth_controller.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import {Request, required, Response} from "../deps.ts";
import {Request, Response} from "oak";
import {required} from "validasaur";
import {LoginCredential} from "../interfaces/LoginCredential.ts";
import * as authService from "../service/user_service.ts";
import {validateRequest} from "../util/validator.ts";

async function login({request, response}: { request: Request; response: Response }) {
const credential = (await request.body().value) as LoginCredential;
await validateCredential(credential);
response.body = await authService.authenticate(credential);
async function login({request, response}: { request: Request; response: Response }): Promise<void> {
const credential = (await request.body().value) as LoginCredential;
await validateCredential(credential);
response.body = await authService.authenticate(credential);
}

async function validateCredential(credential: LoginCredential): Promise<void> {
const credentialSchema = {username: [required], password: [required]};
await validateRequest(credential, credentialSchema);
const credentialSchema = {username: [required], password: [required]};
await validateRequest(credential, credentialSchema);
}

export {login};
95 changes: 48 additions & 47 deletions controller/hero_controller.ts
Original file line number Diff line number Diff line change
@@ -1,83 +1,84 @@
import {lengthBetween, match, oakHelpers, required, RouterContext, Status} from "../deps.ts";
import {helpers as oakHelpers, RouterContext, Status} from "oak";
import {lengthBetween, match, required} from "validasaur";
import {deleteHeroById, findHeroesByName, getHeroById, getHeroesByPage, saveHero} from "../service/hero_service.ts";
import {Hero} from "../entity/hero.ts";
import {parsePageQuery} from "../util/pages.ts";
import {validateRequest} from "../util/validator.ts";

// get heroes
async function getHeroes(context: RouterContext) {
const query = oakHelpers.getQuery(context);
context.response.body = await getHeroesByPage(parsePageQuery(query));
async function getHeroes(context: RouterContext): Promise<void> {
const query = oakHelpers.getQuery(context);
context.response.body = await getHeroesByPage(parsePageQuery(query));
}

// get hero by id
async function getHero(context: RouterContext) {
const {id} = context.params;
await validateId(id);
async function getHero(context: RouterContext): Promise<void> {
const {id} = context.params;
await validateId(id);

if (id) {
context.response.body = await getHeroById(parseInt(id));
}
if (id) {
context.response.body = await getHeroById(parseInt(id));
}
}

// search heroes by name
async function searchHeroes(context: RouterContext) {
const {name} = oakHelpers.getQuery(context);
await validateName(name);
context.response.body = await findHeroesByName(name);
async function searchHeroes(context: RouterContext): Promise<void> {
const {name} = oakHelpers.getQuery(context);
await validateName(name);
context.response.body = await findHeroesByName(name);
}

// add a new hero
async function addHero(context: RouterContext) {
const hero: Hero = await context.request.body().value;
await validateHero(hero);
context.response.body = await saveHero(hero);
async function addHero(context: RouterContext): Promise<void> {
const hero: Hero = await context.request.body().value;
await validateHero(hero);
context.response.body = await saveHero(hero);
}

// update a hero information
async function updateHero(context: RouterContext) {
const hero: Hero = await context.request.body().value;
await validateHero(hero);
context.response.body = await saveHero(hero);
async function updateHero(context: RouterContext): Promise<void> {
const hero: Hero = await context.request.body().value;
await validateHero(hero);
context.response.body = await saveHero(hero);
}

// Delete a hero by id
async function deleteHero(context: RouterContext) {
const {id} = context.params;
await validateId(id);
async function deleteHero(context: RouterContext): Promise<void> {
const {id} = context.params;
await validateId(id);

if (id) {
await deleteHeroById(parseInt(id));
context.response.status = Status.OK;
}
if (id) {
await deleteHeroById(parseInt(id));
context.response.status = Status.OK;
}
}

async function validateHero(hero: Hero): Promise<void> {
const heroSchema = {name: [required, lengthBetween(3, 30)]};
await validateRequest(hero, heroSchema);
const heroSchema = {name: [required, lengthBetween(3, 30)]};
await validateRequest(hero, heroSchema);
}

async function validateId(id: string | undefined): Promise<void> {
await validateRequest(
{id},
{id: [match(/^\d*$/)]},
{messages: {"id": "id must be a number"}}
);
await validateRequest(
{id},
{id: [match(/^\d*$/)]},
{messages: {"id": "id must be a number"}}
);
}

async function validateName(name: string | undefined): Promise<void> {
await validateRequest(
{name},
{name: [required]},
{messages: {"name.required": "Required parameter 'name' is not present"}}
);
await validateRequest(
{name},
{name: [required]},
{messages: {"name.required": "Required parameter 'name' is not present"}}
);
}

export {
addHero,
deleteHero,
getHero,
getHeroes,
searchHeroes,
updateHero,
addHero,
deleteHero,
getHero,
getHeroes,
searchHeroes,
updateHero,
};
Loading

0 comments on commit 75c649a

Please sign in to comment.