Skip to content

Commit fc57f58

Browse files
committed
integration tests
1 parent 6e3d722 commit fc57f58

File tree

11 files changed

+1032
-80
lines changed

11 files changed

+1032
-80
lines changed

docker-compose.test.yml

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ services:
1111
- ./:/usr/src/app
1212
- /usr/src/app/node_modules
1313
- ./test/integration/api.env:/usr/src/app/.env
14+
- ../keycloak:/keycloak:ro
1415
depends_on:
1516
- mongodb
1617
- rabbitmq
18+
- keycloak
1719
# - accounting
1820
stdin_open: true
1921
tty: true
@@ -32,10 +34,20 @@ services:
3234
condition: service_healthy
3335
api:
3436
condition: service_started
35-
command: dockerize -wait http://api:4000/.well-known/apollo/server-health -timeout 30s yarn jest --config=./test/integration/jest.config.js --runInBand test/integration
37+
keycloak:
38+
condition: service_healthy
39+
environment:
40+
- KEYCLOAK_URL=http://keycloak:8180
41+
entrypoint: ["/bin/bash", "-c"]
42+
command:
43+
- |
44+
dockerize -wait http://api:4000/.well-known/apollo/server-health -timeout 30s -wait http://keycloak:8180/health/ready -timeout 60s &&
45+
/keycloak/setup.sh &&
46+
yarn jest --config=./test/integration/jest.config.js --runInBand test/integration
3647
volumes:
3748
- ./:/usr/src/app
3849
- /usr/src/app/node_modules
50+
- ../keycloak:/keycloak:ro
3951

4052
rabbitmq:
4153
image: rabbitmq:3-management
@@ -52,6 +64,29 @@ services:
5264
timeout: 3s
5365
retries: 5
5466

67+
keycloak:
68+
image: quay.io/keycloak/keycloak:23.0
69+
environment:
70+
- KEYCLOAK_ADMIN=admin
71+
- KEYCLOAK_ADMIN_PASSWORD=admin
72+
- KC_HTTP_PORT=8180
73+
- KC_HOSTNAME_STRICT=false
74+
- KC_HOSTNAME_STRICT_HTTPS=false
75+
- KC_HTTP_ENABLED=true
76+
- KC_HEALTH_ENABLED=true
77+
ports:
78+
- 8180:8180
79+
command:
80+
- start-dev
81+
volumes:
82+
- keycloak-test-data:/opt/keycloak/data
83+
- ../keycloak:/opt/keycloak/config
84+
healthcheck:
85+
test: ["CMD-SHELL", "exec 3<>/dev/tcp/127.0.0.1/8180;echo -e 'GET /health/ready HTTP/1.1\r\nhost: http://localhost\r\nConnection: close\r\n\r\n' >&3;if [ $? -eq 0 ]; then echo 'Healthcheck Successful';exit 0;else echo 'Healthcheck Failed';exit 1;fi;"]
86+
interval: 10s
87+
timeout: 5s
88+
retries: 10
89+
5590
# accounting:
5691
# image: codexteamuser/codex-accounting:prod
5792
# env_file:
@@ -61,3 +96,4 @@ services:
6196

6297
volumes:
6398
mongodata-test:
99+
keycloak-test-data:

docker/Dockerfile.dev

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ FROM node:${NODE_VERSION}-alpine
1212

1313
WORKDIR /usr/src/app
1414

15-
RUN apk add --no-cache openssl
15+
RUN apk add --no-cache openssl bash curl
1616

1717
ENV DOCKERIZE_VERSION v0.6.1
1818
RUN wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-alpine-linux-amd64-$DOCKERIZE_VERSION.tar.gz \

package.json

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@shelf/jest-mongodb": "^6.0.2",
2424
"@swc/core": "^1.3.0",
2525
"@types/jest": "^26.0.8",
26+
"@types/xml2js": "^0.4.14",
2627
"eslint": "^6.7.2",
2728
"eslint-config-codex": "1.2.4",
2829
"eslint-plugin-import": "^2.19.1",
@@ -32,7 +33,8 @@
3233
"redis-mock": "^0.56.3",
3334
"ts-jest": "^26.1.4",
3435
"ts-node": "^10.9.1",
35-
"typescript": "^4.7.4"
36+
"typescript": "^4.7.4",
37+
"xml2js": "^0.6.2"
3638
},
3739
"dependencies": {
3840
"@ai-sdk/openai": "^2.0.64",
@@ -41,8 +43,9 @@
4143
"@graphql-tools/schema": "^8.5.1",
4244
"@graphql-tools/utils": "^8.9.0",
4345
"@hawk.so/nodejs": "^3.1.1",
44-
"@hawk.so/types": "^0.4.0",
46+
"@hawk.so/types": "^0.4.2",
4547
"@n1ru4l/json-patch-plus": "^0.2.0",
48+
"@node-saml/node-saml": "^5.0.1",
4649
"@types/amqp-connection-manager": "^2.0.4",
4750
"@types/debug": "^4.1.5",
4851
"@types/escape-html": "^1.0.0",
@@ -57,7 +60,6 @@
5760
"@types/uuid": "^8.3.4",
5861
"ai": "^5.0.89",
5962
"amqp-connection-manager": "^3.1.0",
60-
"@node-saml/node-saml": "^5.0.1",
6163
"amqplib": "^0.5.5",
6264
"apollo-server-express": "^3.10.0",
6365
"argon2": "^0.28.7",

src/resolvers/user.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,15 @@ export default {
9494
): Promise<TokensPair> {
9595
const user = await factories.usersFactory.findByEmail(email);
9696

97-
if (!user || !(await user.comparePassword(password))) {
97+
if (!user) {
9898
throw new AuthenticationError('Wrong email or password');
9999
}
100100

101101
/**
102102
* Check if there is a workspace with enforced SSO
103103
* If user is a member of any workspace with enforced SSO, they must use SSO login
104+
* This check must happen BEFORE password validation to prevent password-based login
105+
* even if the password is correct
104106
*/
105107
const workspacesIds = await user.getWorkspacesIds([]);
106108
const workspaces = await factories.workspacesFactory.findManyByIds(workspacesIds);
@@ -123,6 +125,13 @@ export default {
123125
throw error;
124126
}
125127

128+
/**
129+
* Only validate password if SSO is not enforced
130+
*/
131+
if (!(await user.comparePassword(password))) {
132+
throw new AuthenticationError('Wrong email or password');
133+
}
134+
126135
return user.generateTokensPair();
127136
},
128137

test/integration/api.env

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,16 @@ GITHUB_CLIENT_ID=fakedata
7272
GITHUB_CLIENT_SECRET=fakedata
7373

7474
## Hawk API public url (used in OAuth to redirect to callback, should match OAuth app callback URL)
75-
API_URL=http://127.0.0.1:4000
75+
API_URL=http://localhost:4000
7676

7777
## Garage url
78-
GARAGE_URL=http://127.0.0.1:8080
78+
GARAGE_URL=http://localhost:8080
7979

8080
## Garage login url
81-
GARAGE_LOGIN_URL=http://127.0.0.1:8080/login
81+
GARAGE_LOGIN_URL=http://localhost:8080/login
82+
83+
## SSO Service Provider Entity ID (must match Keycloak client ID)
84+
SSO_SP_ENTITY_ID=urn:hawk:tracker:saml
8285

8386
## Upload dir
8487
UPLOAD_DIR=uploads

0 commit comments

Comments
 (0)