Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Trenten Vollmer
91c72fe386 feat: begin working on client api and pagination 2024-11-22 23:05:43 -05:00
13 changed files with 111 additions and 102 deletions

View file

@ -20,7 +20,6 @@ import { BullConfigService } from './redis/service/bull-config.service';
import { RedisService } from './redis/service/redis.service';
import { OrganizationModule } from './organization/organization.module';
import { ClientModule } from './client/client.module';
import { ViewModule } from './view/view.module';
@Module({
imports: [
@ -72,7 +71,6 @@ import { ViewModule } from './view/view.module';
AuthModule,
OrganizationModule,
ClientModule,
ViewModule,
],
controllers: [AppController],
providers: [AppService],

View file

@ -5,10 +5,10 @@ import {
InternalServerErrorException,
Logger,
Post,
Query,
Req,
Res,
} from '@nestjs/common';
import { ApiExcludeController } from '@nestjs/swagger';
import { AuthService } from '../services/auth.service';
@ -18,9 +18,10 @@ import { InteractionService } from '../oidc/service/interaction.service';
import { OidcService } from '../oidc/service/core.service';
import { InteractionParams, InteractionSession } from '../oidc/types/interaction.type';
import { User } from '../../database/models/user.model';
import { ApiTags } from '@nestjs/swagger';
@Controller('interaction')
@ApiExcludeController()
@ApiTags('Interaction')
export class InteractionController {
constructor(
private readonly authService: AuthService,
@ -31,7 +32,16 @@ export class InteractionController {
logger = new Logger(InteractionController.name);
@Get(':id')
async getUserInteraction(@Res() res: Response, @Req() req: Request, @CurrentUser() user: User) {
async getUserInteraction(
@Res() res: Response,
@Req() req: Request,
@CurrentUser() user: User,
@Query('id') interactionQuery: string,
) {
if (!req.cookies['_interaction'] || !req.cookies['_interaction.sig'] || !interactionQuery) {
throw new BadRequestException('No Interaction found or invalid Interaction');
}
const details: {
session?: InteractionSession;
uid: string;

View file

@ -1,3 +0,0 @@
export class AuthViewController {
constructor() {}
}

View file

@ -2,12 +2,14 @@ import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { RedisModule } from '../redis/redis.module';
import { DATABASE_ENTITIES } from '../database/database.entities';
import { ClientController } from './controller/client.controller';
import { ClientService } from './service/client.service';
import { OidcClient } from '@server/database/models/oidc_client.model';
@Module({
imports: [TypeOrmModule.forFeature(DATABASE_ENTITIES), RedisModule],
controllers: [],
providers: [],
exports: [],
imports: [TypeOrmModule.forFeature([OidcClient]), RedisModule],
controllers: [ClientController],
providers: [ClientService],
exports: [ClientService],
})
export class ClientModule {}

View file

@ -1,6 +1,14 @@
import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { ClientService } from '../service/client.service';
@Controller('organization')
@ApiTags('Clients')
export class ClientsController {}
@Controller('client')
@ApiTags('Client')
export class ClientController {
constructor(private readonly clientService: ClientService) {}
@Get()
async getOrganizations() {
return this.clientService.getClients();
}
}

View file

@ -11,5 +11,10 @@ export class ClientService {
private readonly clientRepository: Repository<OidcClient>,
) {}
public async getClients() {}
public async getClients() {
return await this.clientRepository.find();
}
/** Creates a new client, requires the user to be in an org*/
public async createClient() {}
}

View file

@ -0,0 +1,5 @@
export const PAGINATOR_OPTIONS = Symbol('PAGINATOR_OPTIONS');
export const PAGINATOR_REPOSITORY = Symbol('PAGINATOR_REPOSITORY');
export const PAGINATOR_CURSOR_EXTRACTOR = Symbol('PAGINATOR_CURSOR_EXTRACTOR');
export const PAGINATOR_CURSOR_MAKER = Symbol('PAGINATOR_CURSOR_MAKER');
export const PAGINATOR_ORDER = Symbol('PAGINATOR_ORDER');

View file

@ -0,0 +1,36 @@
import type {
InjectionToken,
ModuleMetadata,
OptionalFactoryDependency,
Provider,
Type,
} from '@nestjs/common';
import type { FindOptionsOrder, FindOptionsWhere, ObjectLiteral, Repository } from 'typeorm';
export type CursorMaker<T> = (entity: T) => string | null;
export type CursorExtractor<E> = (cursor: string) => FindOptionsWhere<E>;
export interface PaginatorModuleOptions<EntityType extends ObjectLiteral> {
repository: Repository<EntityType>;
cursorMaker: CursorMaker<EntityType>;
cursorExtractor: CursorExtractor<EntityType>;
order: FindOptionsOrder<EntityType>;
}
export interface PaginatorModuleOptionsFactory<EntityType extends ObjectLiteral> {
createPaginatorOptions():
| Promise<PaginatorModuleOptions<EntityType>>
| PaginatorModuleOptions<EntityType>;
}
export interface PaginatorModuleAsyncOptions<EntityType extends ObjectLiteral>
extends Pick<ModuleMetadata, 'imports'> {
useExisting?: Type<PaginatorModuleOptionsFactory<EntityType>>;
useClass?: Type<PaginatorModuleOptionsFactory<EntityType>>;
useFactory?: (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...args: any[]
) => Promise<PaginatorModuleOptions<EntityType>> | PaginatorModuleOptions<EntityType>;
inject?: (InjectionToken | OptionalFactoryDependency)[];
extraProviders?: Provider[];
}

View file

@ -11,22 +11,50 @@ import { CurrentUser } from '../../auth/decorators/user.decorator';
export class OrganizationController {
constructor(private readonly organizationService: OrganizationService) {}
@ApiOperation({
summary: 'Create organization',
description: 'Create a new organization',
})
@Post()
public async createOrganization(
@Body() body: CreateOrgDto,
@CurrentUser() user: User,
): Promise<any> {
return await this.organizationService.createOrganization(user.id, body);
}
@ApiOperation({
summary: 'Get organizations',
description: 'Get a paginated list of organizations',
})
@Get()
// Admin: Paginated list of organizations.
public async getOrganizations(): Promise<any> {
return await this.organizationService.getOrganizations();
}
@ApiOperation({
summary: 'Get organization by ID',
description: 'Get an organization by its ID',
})
@Get(':id')
public async getOrganization(@Param('id') id: string): Promise<any> {
return await this.organizationService.getOrganizationById(id);
}
@ApiOperation({
summary: 'Get organization members',
description: 'Get a list of members in an organization',
})
@Get(':id/members')
public async getOrganizationMembers(@Param('id') id: string): Promise<any> {
return await this.organizationService.getOrgMembers(id);
}
@ApiOperation({
summary: 'Delete an organization',
description: 'Delete an organization and all associated data.',
})
@Delete(':id')
public async deleteOrganization(@Param('id') id: string): Promise<any> {
return await this.organizationService.deleteOrganization(id);
@ -35,16 +63,14 @@ export class OrganizationController {
@Patch(':id')
public async partialUpdateOrganization(@Param('id') id: string): Promise<any> {}
@ApiOperation({
summary: "Update's an organization's details",
})
@Put(':id')
public async updateOrganization(@Param('id') id: string): Promise<any> {}
@Post()
public async createOrganization(
@Body() body: CreateOrgDto,
@CurrentUser() user: User,
): Promise<any> {
return await this.organizationService.createOrganization(user.id, body);
}
// === Flags ===
// These are normally handled by Waterwolf to enable certain privileges. Ex. Portal Network
/**
* This sets a flag on the organization.

View file

@ -1,68 +0,0 @@
import { Controller, Get, Render, UseGuards } from '@nestjs/common';
import { ApiExcludeController, ApiExcludeEndpoint } from '@nestjs/swagger';
import { ViewLoginGuard } from '../../auth/guard/viewLogin.guard';
import { CurrentUser } from '../../auth/decorators/user.decorator';
import { User } from '../../database/models/user.model';
@ApiExcludeController()
@Controller()
export class ViewController {
@Get('auth/login')
@Render('auth/login')
@ApiExcludeEndpoint()
@UseGuards(ViewLoginGuard)
public async loginView(): Promise<any> {
return {
forgot_password: 'forgot-password',
register: 'register',
login_url: '/auth/login',
//background_image: 'https://waterwolf.club/static/img/portal/portal7.jpg',
};
}
@Get('auth/login/totp')
@Render('auth/login-totp')
@ApiExcludeEndpoint()
@UseGuards(ViewLoginGuard)
public async getLoginTotp(): Promise<any> {
return {
login: 'login',
methods: ['authenticator', 'email'],
};
}
@Get('auth/register')
@Render('auth/register')
@ApiExcludeEndpoint()
@UseGuards(ViewLoginGuard)
public async getRegister(): Promise<any> {
return {
login: 'login',
};
}
@Get('auth/forgot-password')
@UseGuards(ViewLoginGuard)
@Render('auth/forgot-password')
@ApiExcludeEndpoint()
public async getForgotPassword(): Promise<any> {
return {
login: 'login',
};
}
@Get('home')
@Render('home/index')
@ApiExcludeEndpoint()
@UseGuards(ViewLoginGuard)
public async getHomeView(@CurrentUser() user: User): Promise<any> {
return {
user: {
name: user.displayName ?? user.username,
avatar: user.avatar,
email: user.email,
},
};
}
}

View file

@ -1,10 +0,0 @@
import { Module } from '@nestjs/common';
import { ViewController } from './controllers/view.controller';
@Module({
imports: [],
controllers: [ViewController],
providers: [],
exports: [],
})
export class ViewModule {}