Skip to content

Commit

Permalink
WIP: Building workaround to test payments flow...
Browse files Browse the repository at this point in the history
  • Loading branch information
bonham000 committed Feb 15, 2020
1 parent 6222129 commit dcf7ae9
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 5 deletions.
3 changes: 2 additions & 1 deletion packages/client/src/components/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ class Account extends React.Component<IProps, IState> {
/>
)}
<TextItem>
<Bold>Email:</Bold> {!edit && profile.email}
<Bold>Email:</Bold>{" "}
<span id="user-email">{!edit && profile.email}</span>
</TextItem>
{edit && (
<InputField
Expand Down
1 change: 1 addition & 0 deletions packages/cypress/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
},
"dependencies": {
"@cypress/webpack-preprocessor": "^4.1.1",
"axios": "^0.19.2",
"cypress": "^3.8.1",
"prettier": "^1.19.1",
"ts-loader": "^6.2.1",
Expand Down
24 changes: 23 additions & 1 deletion packages/cypress/src/integration/payment.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { click, TIMEOUT, CLIENT_APP_URL, type } from "../support/cypress-utils";
import axios from "axios";
import { click, TIMEOUT, CLIENT_APP_URL } from "../support/cypress-utils";

/** ===========================================================================
* Auth Tests
Expand All @@ -16,5 +17,26 @@ describe("Payment Course Flow: A user can purchase a course and unlock it's cont
click("course-link-0-purchase");
click("github-login");
cy.wait(TIMEOUT);

cy.contains("Purchase Course");
cy.contains("Start Checkout");
cy.get("body").type("{esc}");

cy.get("#account-menu-dropdown").trigger("mouseover");
cy.get("#account-link").click({ force: true });

let dispatchedAdminRequest = false;
cy.get("#user-email").should(async $div => {
const email = $div.text();

if (!dispatchedAdminRequest) {
console.log("Dispatching admin request!");
axios.post("http://localhost:7000/admin-purchase-course", { email });
dispatchedAdminRequest = true;
}
});

cy.wait(TIMEOUT);
cy.reload();
});
});
3 changes: 2 additions & 1 deletion packages/cypress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
{
"compilerOptions": {
"target": "es5",
"target": "es2017",
"module": "commonjs",
"skipLibCheck": true,
"strict": true,
"esModuleInterop": true,
"types": ["cypress"]
},
"include": ["src/**/*.ts"]
Expand Down
4 changes: 4 additions & 0 deletions packages/external-services/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,9 @@
"prettier": "^1.19.1",
"tslint": "^5.20.1",
"typescript": "^3.7.4"
},
"dependencies": {
"querystring": "^0.2.0",
"supertest": "^4.0.2"
}
}
58 changes: 58 additions & 0 deletions packages/external-services/src/admin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import axios from "axios";
import querystring from "querystring";
import request from "supertest";

export const purchaseCourseForUserByAdmin = async (userEmail: string) => {
const accessToken = await getAccessTokenForAdmin();

const result = await axios.post(
`http://localhost:9000/admin/course-pay`,
{
userEmail,
courseId: "fpvPtfu7s",
},
{
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);

return "OK";
};

const getAccessTokenFromRedirect = (redirect: string) => {
const indexOfQuestionMark = redirect.indexOf("?");
const queryParams = redirect.slice(indexOfQuestionMark + 1);
const params = querystring.parse(queryParams);
return params.accessToken;
};

const getAccessTokenForAdmin = async (): Promise<string> => {
let authorizationRedirect;
let loginRedirect;
let accessToken;

await request(`http://localhost:9000/auth/google`)
.get("/")
.expect(302)
.then(response => {
authorizationRedirect = response.header.location;
});

await request(authorizationRedirect)
.get("/")
.expect(302)
.then(response => {
loginRedirect = response.header.location;
});

await request(loginRedirect)
.get("/")
.expect(302)
.then(response => {
accessToken = getAccessTokenFromRedirect(response.header.location);
});

return accessToken;
};
10 changes: 9 additions & 1 deletion packages/external-services/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import cors from "cors";
import express from "express";
import morgan from "morgan";
import mockAuth from "./mock-auth";
import { purchaseCourseForUserByAdmin } from "./admin";
import dotenv from "dotenv";
import { exec } from "child_process";

dotenv.config();

Expand Down Expand Up @@ -104,6 +104,14 @@ app.get("/google/profile", (req, res) => {
res.json(profile);
});

/**
* Admin API to handle purchasing a course for a user.
*/
app.post("/admin-purchase-course", (req, res) => {
const { email } = req.body;
purchaseCourseForUserByAdmin(email);
});

/** ===========================================================================
* Run the Server
* ============================================================================
Expand Down
20 changes: 19 additions & 1 deletion packages/server/src/admin/admin.controller.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
import { Request, Controller, UseGuards, Get, Param } from "@nestjs/common";
import {
Request,
Controller,
UseGuards,
Get,
Param,
Post,
Body,
} from "@nestjs/common";
import { AdminAuthGuard } from "src/auth/admin.guard";
import { AuthenticatedRequest } from "src/types";
import { AdminService } from "./admin.service";
import { PaymentsService } from "src/payments/payments.service";
import { SUCCESS_CODES } from "src/tools/constants";

@Controller("admin")
export class AdminController {
Expand All @@ -23,4 +33,12 @@ export class AdminController {
const { challengeId } = params;
return this.adminService.getFeedbackForChallenge(challengeId);
}

@UseGuards(AdminAuthGuard)
@Post("/course-pay")
async purchaseCourseForUser(@Body() body) {
const { courseId, userEmail } = body;
// await this.paymentsService.handlePurchaseCourseByAdmin(courseId, userEmail);
return SUCCESS_CODES.OK;
}
}
7 changes: 7 additions & 0 deletions packages/server/src/payments/payments.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ export class PaymentsService {
return SUCCESS_CODES.OK;
}

async handlePurchaseCourseByAdmin(userEmail: string, courseId: string) {
console.log(
`[ADMIN]: Admin request to purchase course: ${courseId} for user: ${userEmail}`,
);
this.handlePurchaseCourseRequest(userEmail, courseId);
}

private async handlePurchaseCourseRequest(
userEmail: string,
courseId: string,
Expand Down
7 changes: 7 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5526,6 +5526,13 @@ axios@0.19.0, axios@^0.19.0:
follow-redirects "1.5.10"
is-buffer "^2.0.2"

axios@^0.19.2:
version "0.19.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
dependencies:
follow-redirects "1.5.10"

axobject-query@^2.0.2:
version "2.1.1"
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.1.1.tgz#2a3b1271ec722d48a4cd4b3fcc20c853326a49a7"
Expand Down

0 comments on commit dcf7ae9

Please sign in to comment.