feat(opsserver,web): replace the Angular UI and REST management layer with a TypedRequest-based ops server and bundled web frontend
This commit is contained in:
@@ -6,7 +6,11 @@ import { User } from '../../ts/models/user.ts';
|
||||
import { ApiToken } from '../../ts/models/apitoken.ts';
|
||||
import { AuthService } from '../../ts/services/auth.service.ts';
|
||||
import { TokenService } from '../../ts/services/token.service.ts';
|
||||
import type { TRegistryProtocol, ITokenScope, TUserStatus } from '../../ts/interfaces/auth.interfaces.ts';
|
||||
import type {
|
||||
ITokenScope,
|
||||
TRegistryProtocol,
|
||||
TUserStatus,
|
||||
} from '../../ts/interfaces/auth.interfaces.ts';
|
||||
import { testConfig } from '../test.config.ts';
|
||||
|
||||
const TEST_PASSWORD = 'TestPassword123!';
|
||||
@@ -25,7 +29,7 @@ export interface ICreateTestUserOptions {
|
||||
* Create a test user with sensible defaults
|
||||
*/
|
||||
export async function createTestUser(
|
||||
overrides: ICreateTestUserOptions = {}
|
||||
overrides: ICreateTestUserOptions = {},
|
||||
): Promise<{ user: User; password: string }> {
|
||||
const uniqueId = crypto.randomUUID().slice(0, 8);
|
||||
const password = overrides.password || TEST_PASSWORD;
|
||||
@@ -61,7 +65,7 @@ export async function createAdminUser(): Promise<{ user: User; password: string
|
||||
*/
|
||||
export async function loginUser(
|
||||
email: string,
|
||||
password: string
|
||||
password: string,
|
||||
): Promise<{ accessToken: string; refreshToken: string; sessionId: string }> {
|
||||
const authService = new AuthService({
|
||||
jwtSecret: testConfig.jwt.secret,
|
||||
@@ -96,7 +100,7 @@ export interface ICreateTestApiTokenOptions {
|
||||
* Create test API token
|
||||
*/
|
||||
export async function createTestApiToken(
|
||||
options: ICreateTestApiTokenOptions
|
||||
options: ICreateTestApiTokenOptions,
|
||||
): Promise<{ rawToken: string; token: ApiToken }> {
|
||||
const tokenService = new TokenService();
|
||||
|
||||
@@ -127,7 +131,7 @@ export function createAuthHeader(token: string): { Authorization: string } {
|
||||
*/
|
||||
export function createBasicAuthHeader(
|
||||
username: string,
|
||||
password: string
|
||||
password: string,
|
||||
): { Authorization: string } {
|
||||
const credentials = btoa(`${username}:${password}`);
|
||||
return { Authorization: `Basic ${credentials}` };
|
||||
|
||||
@@ -15,7 +15,7 @@ let isConnected = false;
|
||||
|
||||
// We need to patch the global db export since models reference it
|
||||
// This is done by re-initializing with the test config
|
||||
import { initDb, closeDb } from '../../ts/models/db.ts';
|
||||
import { closeDb, initDb } from '../../ts/models/db.ts';
|
||||
|
||||
/**
|
||||
* Initialize test database with unique name per test run
|
||||
|
||||
@@ -11,10 +11,10 @@ import { Package } from '../../ts/models/package.ts';
|
||||
import { RepositoryPermission } from '../../ts/models/repository.permission.ts';
|
||||
import type {
|
||||
TOrganizationRole,
|
||||
TTeamRole,
|
||||
TRegistryProtocol,
|
||||
TRepositoryRole,
|
||||
TRepositoryVisibility,
|
||||
TRegistryProtocol,
|
||||
TTeamRole,
|
||||
} from '../../ts/interfaces/auth.interfaces.ts';
|
||||
|
||||
export interface ICreateTestOrganizationOptions {
|
||||
@@ -29,7 +29,7 @@ export interface ICreateTestOrganizationOptions {
|
||||
* Create test organization
|
||||
*/
|
||||
export async function createTestOrganization(
|
||||
options: ICreateTestOrganizationOptions
|
||||
options: ICreateTestOrganizationOptions,
|
||||
): Promise<Organization> {
|
||||
const uniqueId = crypto.randomUUID().slice(0, 8);
|
||||
|
||||
@@ -53,7 +53,7 @@ export async function createTestOrganization(
|
||||
*/
|
||||
export async function createOrgWithOwner(
|
||||
ownerId: string,
|
||||
orgOptions?: Partial<ICreateTestOrganizationOptions>
|
||||
orgOptions?: Partial<ICreateTestOrganizationOptions>,
|
||||
): Promise<{
|
||||
organization: Organization;
|
||||
membership: OrganizationMember;
|
||||
@@ -82,7 +82,7 @@ export async function addOrgMember(
|
||||
organizationId: string,
|
||||
userId: string,
|
||||
role: TOrganizationRole = 'member',
|
||||
invitedBy?: string
|
||||
invitedBy?: string,
|
||||
): Promise<OrganizationMember> {
|
||||
const membership = await OrganizationMember.addMember({
|
||||
organizationId,
|
||||
@@ -113,7 +113,7 @@ export interface ICreateTestRepositoryOptions {
|
||||
* Create test repository
|
||||
*/
|
||||
export async function createTestRepository(
|
||||
options: ICreateTestRepositoryOptions
|
||||
options: ICreateTestRepositoryOptions,
|
||||
): Promise<Repository> {
|
||||
const uniqueId = crypto.randomUUID().slice(0, 8);
|
||||
|
||||
@@ -152,7 +152,7 @@ export async function createTestTeam(options: ICreateTestTeamOptions): Promise<T
|
||||
export async function addTeamMember(
|
||||
teamId: string,
|
||||
userId: string,
|
||||
role: TTeamRole = 'member'
|
||||
role: TTeamRole = 'member',
|
||||
): Promise<TeamMember> {
|
||||
const member = new TeamMember();
|
||||
member.id = await TeamMember.getNewId();
|
||||
@@ -176,7 +176,7 @@ export interface IGrantRepoPermissionOptions {
|
||||
* Grant repository permission
|
||||
*/
|
||||
export async function grantRepoPermission(
|
||||
options: IGrantRepoPermissionOptions
|
||||
options: IGrantRepoPermissionOptions,
|
||||
): Promise<RepositoryPermission> {
|
||||
const perm = new RepositoryPermission();
|
||||
perm.id = await RepositoryPermission.getNewId();
|
||||
|
||||
@@ -75,7 +75,7 @@ export const del = (path: string, headers?: Record<string, string>) =>
|
||||
export function assertStatus(response: ITestResponse, expected: number): void {
|
||||
if (response.status !== expected) {
|
||||
throw new Error(
|
||||
`Expected status ${expected} but got ${response.status}: ${JSON.stringify(response.body)}`
|
||||
`Expected status ${expected} but got ${response.status}: ${JSON.stringify(response.body)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ export function assertBodyHas(response: ITestResponse, keys: string[]): void {
|
||||
export function assertSuccess(response: ITestResponse): void {
|
||||
if (response.status < 200 || response.status >= 300) {
|
||||
throw new Error(
|
||||
`Expected successful response but got ${response.status}: ${JSON.stringify(response.body)}`
|
||||
`Expected successful response but got ${response.status}: ${JSON.stringify(response.body)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,82 +4,82 @@
|
||||
|
||||
// Database helpers
|
||||
export {
|
||||
setupTestDb,
|
||||
cleanupTestDb,
|
||||
teardownTestDb,
|
||||
clearCollections,
|
||||
getTestDbName,
|
||||
getTestDb,
|
||||
getTestDbName,
|
||||
setupTestDb,
|
||||
teardownTestDb,
|
||||
} from './db.helper.ts';
|
||||
|
||||
// Auth helpers
|
||||
export {
|
||||
createTestUser,
|
||||
createAdminUser,
|
||||
loginUser,
|
||||
createTestApiToken,
|
||||
createAuthHeader,
|
||||
createBasicAuthHeader,
|
||||
createTestApiToken,
|
||||
createTestUser,
|
||||
getTestPassword,
|
||||
type ICreateTestUserOptions,
|
||||
type ICreateTestApiTokenOptions,
|
||||
type ICreateTestUserOptions,
|
||||
loginUser,
|
||||
} from './auth.helper.ts';
|
||||
|
||||
// Factory helpers
|
||||
export {
|
||||
createTestOrganization,
|
||||
createOrgWithOwner,
|
||||
addOrgMember,
|
||||
addTeamMember,
|
||||
createFullTestScenario,
|
||||
createOrgWithOwner,
|
||||
createTestOrganization,
|
||||
createTestPackage,
|
||||
createTestRepository,
|
||||
createTestTeam,
|
||||
addTeamMember,
|
||||
grantRepoPermission,
|
||||
createTestPackage,
|
||||
createFullTestScenario,
|
||||
type ICreateTestOrganizationOptions,
|
||||
type ICreateTestPackageOptions,
|
||||
type ICreateTestRepositoryOptions,
|
||||
type ICreateTestTeamOptions,
|
||||
type IGrantRepoPermissionOptions,
|
||||
type ICreateTestPackageOptions,
|
||||
} from './factory.helper.ts';
|
||||
|
||||
// HTTP helpers
|
||||
export {
|
||||
testRequest,
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
patch,
|
||||
del,
|
||||
assertStatus,
|
||||
assertBodyHas,
|
||||
assertSuccess,
|
||||
assertError,
|
||||
assertStatus,
|
||||
assertSuccess,
|
||||
del,
|
||||
get,
|
||||
type ITestRequest,
|
||||
type ITestResponse,
|
||||
patch,
|
||||
post,
|
||||
put,
|
||||
testRequest,
|
||||
} from './http.helper.ts';
|
||||
|
||||
// Subprocess helpers
|
||||
export {
|
||||
runCommand,
|
||||
commandExists,
|
||||
clients,
|
||||
skipIfMissing,
|
||||
type ICommandResult,
|
||||
commandExists,
|
||||
type ICommandOptions,
|
||||
type ICommandResult,
|
||||
runCommand,
|
||||
skipIfMissing,
|
||||
} from './subprocess.helper.ts';
|
||||
|
||||
// Storage helpers
|
||||
export {
|
||||
setupTestStorage,
|
||||
checkStorageAvailable,
|
||||
objectExists,
|
||||
listObjects,
|
||||
cleanupTestStorage,
|
||||
deleteObject,
|
||||
deletePrefix,
|
||||
cleanupTestStorage,
|
||||
isStorageAvailable,
|
||||
listObjects,
|
||||
objectExists,
|
||||
setupTestStorage,
|
||||
} from './storage.helper.ts';
|
||||
|
||||
// Re-export test config
|
||||
export { testConfig, getTestConfig } from '../test.config.ts';
|
||||
export { getTestConfig, testConfig } from '../test.config.ts';
|
||||
|
||||
@@ -22,7 +22,7 @@ export interface ICommandOptions {
|
||||
*/
|
||||
export async function runCommand(
|
||||
cmd: string[],
|
||||
options: ICommandOptions = {}
|
||||
options: ICommandOptions = {},
|
||||
): Promise<ICommandResult> {
|
||||
const { cwd, env, timeout = 60000, stdin } = options;
|
||||
|
||||
@@ -116,7 +116,7 @@ export const clients = {
|
||||
publish: (dir: string, registry: string, token: string) =>
|
||||
runCommand(
|
||||
['cargo', 'publish', '--registry', 'stack-test', '--token', token, '--allow-dirty'],
|
||||
{ cwd: dir }
|
||||
{ cwd: dir },
|
||||
),
|
||||
yank: (crate: string, version: string, token: string) =>
|
||||
runCommand([
|
||||
@@ -164,7 +164,7 @@ export const clients = {
|
||||
'--repository',
|
||||
JSON.stringify({ type: 'composer', url: repository }),
|
||||
],
|
||||
{ cwd: dir }
|
||||
{ cwd: dir },
|
||||
),
|
||||
},
|
||||
|
||||
@@ -190,7 +190,7 @@ export const clients = {
|
||||
`-Dusername=${username}`,
|
||||
`-Dpassword=${password}`,
|
||||
],
|
||||
{ cwd: dir }
|
||||
{ cwd: dir },
|
||||
),
|
||||
package: (dir: string) => runCommand(['mvn', 'package', '-DskipTests'], { cwd: dir }),
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user