Skip to content

Commit 42b51f3

Browse files
committed
wip: adding db tests for auth provider server
1 parent 8a935a4 commit 42b51f3

File tree

3 files changed

+192
-1
lines changed

3 files changed

+192
-1
lines changed

components/gitpod-db/src/typeorm/entity/db-auth-provider-entry.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@ export class DBAuthProviderEntry implements AuthProviderEntry {
1818
@Column()
1919
ownerId: string;
2020

21-
@Column()
21+
@Column({
22+
...TypeORM.UUID_COLUMN_TYPE,
23+
default: "",
24+
transformer: Transformer.MAP_EMPTY_STR_TO_UNDEFINED,
25+
})
2226
organizationId?: string;
2327

2428
@Column("varchar")
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/**
2+
* Copyright (c) 2023 Gitpod GmbH. All rights reserved.
3+
* Licensed under the GNU Affero General Public License (AGPL).
4+
* See License.AGPL.txt in the project root for license information.
5+
*/
6+
7+
import { TypeORM } from "@gitpod/gitpod-db/lib";
8+
import { Organization, User } from "@gitpod/gitpod-protocol";
9+
import { Experiments } from "@gitpod/gitpod-protocol/lib/experiments/configcat-server";
10+
import * as chai from "chai";
11+
import { Container } from "inversify";
12+
import "mocha";
13+
import { createTestContainer } from "../test/service-testing-container-module";
14+
import { resetDB } from "@gitpod/gitpod-db/lib/test/reset-db";
15+
import { UserService } from "../user/user-service";
16+
import { AuthProviderService } from "./auth-provider-service";
17+
import { Config } from "../config";
18+
import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
19+
import { expectError } from "../test/expect-utils";
20+
import { AuthProviderEntry } from "@gitpod/gitpod-protocol";
21+
import { AuthProviderParams } from "./auth-provider";
22+
import { OrganizationService } from "../orgs/organization-service";
23+
24+
const expect = chai.expect;
25+
26+
describe("AuthProviderService", async () => {
27+
let service: AuthProviderService;
28+
let container: Container;
29+
let owner: User;
30+
let org: Organization;
31+
32+
const newEntry = () =>
33+
<AuthProviderEntry.NewEntry>{
34+
host: "github.com",
35+
ownerId: owner.id,
36+
type: "GitHub",
37+
clientId: "123",
38+
clientSecret: "secret-123",
39+
};
40+
const expectedProviderPartial = () =>
41+
<Partial<AuthProviderParams>>{
42+
builtin: false,
43+
host: "github.com",
44+
disallowLogin: false,
45+
oauth: {
46+
authorizationUrl: "https://github.com/login/oauth/authorize",
47+
callBackUrl: "https://gitpod.io/auth/callback",
48+
clientId: "123",
49+
clientSecret: "secret-123",
50+
tokenUrl: "https://github.com/login/oauth/access_token",
51+
},
52+
organizationId: undefined,
53+
type: "GitHub",
54+
verified: false,
55+
status: "pending",
56+
ownerId: owner.id,
57+
};
58+
59+
const newOrgEntry = () =>
60+
<AuthProviderEntry.NewOrgEntry>{
61+
host: "github.com",
62+
ownerId: owner.id,
63+
type: "GitHub",
64+
clientId: "123",
65+
clientSecret: "secret-123",
66+
organizationId: org.id,
67+
};
68+
const expectedOrgProviderPartial = () =>
69+
<Partial<AuthProviderParams>>{
70+
builtin: false,
71+
host: "github.com",
72+
disallowLogin: true,
73+
oauth: {
74+
authorizationUrl: "https://github.com/login/oauth/authorize",
75+
callBackUrl: "https://gitpod.io/auth/callback",
76+
clientId: "123",
77+
clientSecret: "secret-123",
78+
tokenUrl: "https://github.com/login/oauth/access_token",
79+
},
80+
organizationId: org.id,
81+
type: "GitHub",
82+
verified: false,
83+
status: "pending",
84+
ownerId: owner.id,
85+
};
86+
87+
beforeEach(async () => {
88+
container = createTestContainer();
89+
Experiments.configureTestingClient({
90+
centralizedPermissions: true,
91+
});
92+
service = container.get(AuthProviderService);
93+
const userService = container.get<UserService>(UserService);
94+
owner = await userService.createUser({
95+
identity: {
96+
authId: "gh-user-1",
97+
authName: "user",
98+
authProviderId: "public-github",
99+
},
100+
});
101+
const os = container.get<OrganizationService>(OrganizationService);
102+
org = await os.createOrganization(owner.id, "myorg");
103+
});
104+
105+
afterEach(async () => {
106+
// Clean-up database
107+
await resetDB(container.get(TypeORM));
108+
});
109+
110+
describe("createAuthProviderOfUser", async () => {
111+
it("should create user-level provider", async () => {
112+
const providersAtStart = await service.getAllAuthProviders();
113+
expect(providersAtStart).to.be.empty;
114+
115+
await service.createAuthProviderOfUser(owner.id, newEntry());
116+
117+
const providers = await service.getAllAuthProviders();
118+
expect(providers).to.have.lengthOf(1);
119+
expect(providers[0]).to.deep.include(expectedProviderPartial());
120+
});
121+
122+
it("should fail in case of conflict with built-in provider", async () => {
123+
const config = container.get<Config>(Config);
124+
config.builtinAuthProvidersConfigured = true;
125+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
126+
config.authProviderConfigs.push({
127+
host: "github.com",
128+
} as any);
129+
130+
const providersAtStart = await service.getAllAuthProviders();
131+
expect(providersAtStart).to.be.empty;
132+
133+
await expectError(ErrorCodes.CONFLICT, service.createAuthProviderOfUser(owner.id, newEntry()));
134+
});
135+
it("should fail if host is not reachable", async () => {
136+
await expectError(
137+
ErrorCodes.BAD_REQUEST,
138+
service.createAuthProviderOfUser(owner.id, {
139+
...newEntry(),
140+
host: "please-dont-register-this-domain.com:666",
141+
}),
142+
);
143+
});
144+
it("should fail if trying to register same host", async () => {
145+
const providersAtStart = await service.getAllAuthProviders();
146+
expect(providersAtStart).to.be.empty;
147+
148+
await service.createAuthProviderOfUser(owner.id, newEntry());
149+
150+
await expectError(ErrorCodes.CONFLICT, service.createAuthProviderOfUser(owner.id, newEntry()));
151+
});
152+
});
153+
154+
describe("createOrgAuthProvider", async () => {
155+
it("should create org-level provider", async () => {
156+
const providersAtStart = await service.getAllAuthProviders();
157+
expect(providersAtStart).to.be.empty;
158+
159+
await service.createOrgAuthProvider(owner.id, newOrgEntry());
160+
161+
const providers = await service.getAllAuthProviders();
162+
expect(providers).to.have.lengthOf(1);
163+
expect(providers[0]).to.deep.include(expectedOrgProviderPartial());
164+
});
165+
it("should fail if host is not reachable", async () => {
166+
await expectError(
167+
ErrorCodes.BAD_REQUEST,
168+
service.createOrgAuthProvider(owner.id, {
169+
...newOrgEntry(),
170+
host: "please-dont-register-this-domain.com:666",
171+
}),
172+
);
173+
});
174+
it("should fail if trying to register same host", async () => {
175+
const providersAtStart = await service.getAllAuthProviders();
176+
expect(providersAtStart).to.be.empty;
177+
178+
await service.createOrgAuthProvider(owner.id, newOrgEntry());
179+
180+
await expectError(ErrorCodes.CONFLICT, service.createAuthProviderOfUser(owner.id, newOrgEntry()));
181+
});
182+
});
183+
});

components/server/src/auth/auth-provider.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ export interface AuthProviderParams extends AuthProviderEntry {
1818

1919
// properties to control behavior
2020
readonly hiddenOnDashboard?: boolean;
21+
22+
/**
23+
* @deprecated: looks like this is unused after all
24+
*/
2125
readonly disallowLogin?: boolean;
2226

2327
readonly description: string;

0 commit comments

Comments
 (0)