Skip to content

Commit 8454854

Browse files
committed
chore: exposing consent list
1 parent 76a110f commit 8454854

File tree

7 files changed

+433
-230
lines changed

7 files changed

+433
-230
lines changed

apps/dashboard/cypress/e2e/consent-integration.cy.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,6 @@ describe("Consent integration Test", () => {
3232
cy.get("[data-testid=verification_code_input]").should("not.be.disabled")
3333
cy.get("[data-testid=verification_code_input]").type(code)
3434

35-
cy.contains("label", "read").should("exist")
36-
cy.contains("label", "read").should("be.visible")
37-
cy.contains("label", "read").should("not.be.disabled")
38-
cy.contains("label", "read").should("not.be.disabled")
39-
cy.contains("label", "read").click()
40-
41-
cy.contains("label", "write").should("exist")
42-
cy.contains("label", "write").should("be.visible")
43-
cy.contains("label", "write").should("not.be.disabled")
44-
cy.contains("label", "write").click()
45-
46-
cy.get("[data-testid=submit_consent_btn]").should("exist")
47-
cy.get("[data-testid=submit_consent_btn]").should("be.visible")
48-
cy.get("[data-testid=submit_consent_btn]").should("not.be.disabled")
49-
cy.get("[data-testid=submit_consent_btn]").click()
50-
5135
cy.url().should("eq", Cypress.config().baseUrl + "/")
5236
cy.getCookie("next-auth.session-token").then((cookie) => {
5337
if (cookie && cookie.value) {

apps/voucher/cypress/e2e/consent-integration.cy.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,22 +32,6 @@ describe("Consent integration Test", () => {
3232
cy.get("[data-testid=verification_code_input]").should("not.be.disabled")
3333
cy.get("[data-testid=verification_code_input]").type(code)
3434

35-
cy.contains("label", "read").should("exist")
36-
cy.contains("label", "read").should("be.visible")
37-
cy.contains("label", "read").should("not.be.disabled")
38-
cy.contains("label", "read").should("not.be.disabled")
39-
cy.contains("label", "read").click()
40-
41-
cy.contains("label", "write").should("exist")
42-
cy.contains("label", "write").should("be.visible")
43-
cy.contains("label", "write").should("not.be.disabled")
44-
cy.contains("label", "write").click()
45-
46-
cy.get("[data-testid=submit_consent_btn]").should("exist")
47-
cy.get("[data-testid=submit_consent_btn]").should("be.visible")
48-
cy.get("[data-testid=submit_consent_btn]").should("not.be.disabled")
49-
cy.get("[data-testid=submit_consent_btn]").click()
50-
5135
cy.url().should("eq", Cypress.config().baseUrl + "/")
5236
cy.getCookie("next-auth.session-token").then((cookie) => {
5337
if (cookie && cookie.value) {

core/api/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
"@typescript-eslint/parser": "^7.7.0",
162162
"@xascode/tscpaths": "0.1.4",
163163
"axios-mock-adapter": "^1.22.0",
164+
"child_process": "^1.0.2",
164165
"eslint": "^8.57.0",
165166
"eslint-config-prettier": "^9.1.0",
166167
"eslint-plugin-import": "^2.29.1",
@@ -182,6 +183,7 @@
182183
"pino-pretty": "^10.3.1",
183184
"prettier": "^3.2.5",
184185
"protoc-gen-js": "^3.21.2",
186+
"puppeteer": "^22.7.1",
185187
"react": "^18.2.0",
186188
"spectaql": "^2.3.1",
187189
"tiny-secp256k1": "^2.2.3",

core/api/src/services/hydra/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ export const consentList = async (userId: UserId): Promise<ConsentSession[]> =>
1818
let sessions: ConsentSession[]
1919

2020
try {
21-
console.dir(res.data, { depth: null })
21+
/* eslint @typescript-eslint/ban-ts-comment: "off" */
22+
// @ts-ignore-next-line no-implicit-any error
2223
sessions = res.data.map((request) => ({
2324
scope: request.grant_scope,
2425
handledAt: new Date(request.handled_at),
Lines changed: 76 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,82 @@
1+
import { Admin } from "@/app"
12
import { consentList } from "@/services/hydra"
2-
import axios from "axios"
3-
4-
import { createUserAndWalletFromPhone, getUserIdByPhone, randomPhone } from "test/helpers"
3+
import { sleep } from "@/utils"
4+
import { exec } from "child_process"
5+
import puppeteer from "puppeteer"
56

67
let userId: UserId
7-
const phone = randomPhone()
8-
// const phone = "+14152991378" as PhoneNumber
9-
10-
const redirectUri = "http://localhost/callback"
11-
const scope = "offline read write"
12-
const grant_types = ["authorization_code", "refresh_token"]
8+
const email = "test@galoy.io" as EmailAddress
139

1410
beforeAll(async () => {
15-
await createUserAndWalletFromPhone(phone)
16-
userId = await getUserIdByPhone(phone)
11+
const account = await Admin.getAccountByUserEmail(email)
12+
if (account instanceof Error) throw account
13+
14+
userId = account.kratosUserId
1715
})
1816

19-
async function createOAuthClient() {
20-
const hydraAdminUrl = "http://localhost:4445/admin/clients"
21-
22-
try {
23-
const response = await axios.post(hydraAdminUrl, {
24-
client_name: "integration_test",
25-
grant_types,
26-
response_types: ["code", "id_token"],
27-
redirect_uris: [redirectUri],
28-
scope,
29-
skip_consent: true,
17+
const getOTP = (email: string): Promise<string> => {
18+
return new Promise((resolve, reject) => {
19+
const query = `docker exec -i galoy-dev-kratos-pg-1 psql -U dbuser -d default -t -c "SELECT body FROM courier_messages WHERE recipient='${email}' ORDER BY created_at DESC LIMIT 1;"`
20+
exec(query, (error, stdout, stderr) => {
21+
if (error) {
22+
reject(`error: ${error.message}`)
23+
return
24+
}
25+
if (stderr) {
26+
reject(`stderr: ${stderr}`)
27+
return
28+
}
29+
const otpMatch = stdout.match(/(\d{6})/)
30+
if (otpMatch && otpMatch[1]) {
31+
resolve(otpMatch[1])
32+
} else {
33+
reject("OTP not found in the message")
34+
}
3035
})
36+
})
37+
}
3138

32-
const clientId = response.data.client_id
33-
const clientSecret = response.data.client_secret
39+
async function performOAuthLogin() {
40+
const screenshots = false
3441

35-
return { clientId, clientSecret }
36-
} catch (error) {
37-
console.error("Error creating OAuth client:", error.response)
38-
}
39-
}
42+
const browser = await puppeteer.launch()
43+
// const browser = await puppeteer.launch({ headless: true })
44+
const page = await browser.newPage()
4045

41-
async function performOAuthLogin({
42-
clientId,
43-
clientSecret,
44-
}: {
45-
clientId: string
46-
clientSecret: string
47-
}) {
48-
// create oauth2 client
49-
50-
const responseType = "code"
51-
const randomState = "MKfNw-q60talMJ4GU_h1kHFvcPtnQkZI0XLpTkHvJL4"
52-
53-
const authUrl = `http://localhost:4444/oauth2/auth?response_type=${responseType}&client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&state=${randomState}`
54-
55-
// https://oauth.blink.sv/oauth2/auth?client_id=73ae7c3e-e526-412a-856c-25d1ae0cbc55&scope=read%20write&response_type=code&redirect_uri=https%3A%2F%2Fdashboard.blink.sv%2Fapi%2Fauth%2Fcallback%2Fblink&state=MKfNw-q60talMJ4GU_h1kHFvcPtnQkZI0XLpTkHvJL4
56-
57-
// Simulate user going to the authorization URL and logging in
58-
// This part would require a real user interaction or a browser automation tool like puppeteer
59-
60-
let data
61-
try {
62-
const res = await axios.get(authUrl)
63-
data = res.data
64-
} catch (error) {
65-
console.error("Error getting auth URL:", error)
66-
return
67-
}
68-
69-
// You need to extract the code from the callback response
70-
const code = data.code // Simplified: Actual extraction depends on your OAuth provider
71-
72-
console.log("data", data)
73-
console.log("code", code)
74-
75-
try {
76-
// Exchange the code for a token
77-
const tokenResponse = await axios.post("http://localhost:4444/oauth2/token", {
78-
code,
79-
redirect_uri: redirectUri,
80-
client_id: clientId,
81-
client_secret: clientSecret,
82-
grant_type: "authorization_code",
83-
})
46+
// Navigate the page to a URL
47+
await page.goto("http://localhost:3001/api/auth/signin")
48+
49+
screenshots && (await page.screenshot({ path: "screenshot0.png" }))
8450

85-
const accessToken = tokenResponse.data.access_token
51+
await page.waitForSelector(".button")
52+
await page.click(".button")
8653

87-
// Use the access token to get user info or other secured resources
88-
// Update the consent list as needed
89-
return accessToken // This might be used for further secured requests
90-
} catch (error) {
91-
console.error("Error exchanging code for token:", error)
92-
}
54+
screenshots && (await page.screenshot({ path: "screenshot1.png" }))
55+
56+
await page.waitForSelector('[data-testid="email_id_input"]')
57+
await page.waitForFunction(
58+
"document.querySelector(\"[data-testid='email_id_input']\").isConnected",
59+
)
60+
await page.type('[data-testid="email_id_input"]', email)
61+
screenshots && (await page.screenshot({ path: "screenshot2.png" }))
62+
await sleep(250)
63+
64+
await page.click("#accept")
65+
66+
await sleep(500)
67+
screenshots && (await page.screenshot({ path: "screenshot3.png" }))
68+
69+
const otp = await getOTP(email)
70+
71+
await page.waitForSelector("#code")
72+
await page.type("#code", otp, { delay: 100 })
73+
74+
screenshots && (await page.screenshot({ path: "screenshot4.png" }))
75+
await sleep(1500)
76+
screenshots && (await page.screenshot({ path: "screenshot5.png" }))
77+
78+
await page.close()
79+
await browser.close()
9380
}
9481

9582
describe("Hydra", () => {
@@ -99,12 +86,16 @@ describe("Hydra", () => {
9986
})
10087

10188
it("get consent list when the user had perform oauth2 login", async () => {
102-
const res = await createOAuthClient()
103-
if (!res) return
104-
const { clientId, clientSecret } = res
105-
console.log("clientId", clientId, "clientSecret", clientSecret)
89+
await performOAuthLogin()
10690

107-
const accessToken = await performOAuthLogin({ clientId, clientSecret })
108-
console.log("accessToken", accessToken)
91+
const res = await consentList(userId)
92+
expect(res).toEqual([
93+
{
94+
app: "dashboard",
95+
handledAt: expect.any(Date),
96+
remember: false,
97+
scope: ["read", "write"],
98+
},
99+
])
109100
})
110101
})

dev/bin/setup-hydra-client.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ hydra_cli create client \
2121
--format json \
2222
--scope read --scope write \
2323
--redirect-uri "$redirect_uri" > "${HYDRA_CLIENT_JSON}" \
24-
--name "${hydra_client_name}"
24+
--name "${hydra_client_name}" \
25+
--skip-consent
2526

2627
CLIENT_ID=$(jq -r '.client_id' < "${HYDRA_CLIENT_JSON}")
2728
CLIENT_SECRET=$(jq -r '.client_secret' < "${HYDRA_CLIENT_JSON}")

0 commit comments

Comments
 (0)