Skip to content

Commit

Permalink
Merge stage prior to release v1.1.0 (#145)
Browse files Browse the repository at this point in the history
* Feature/IOT_16_MulticastBackend (#132)

* Made CRUD operationer for multicast. Tested with frontend.

* Made CRUD for multicast in backend plus connection to chirpStack.

* Changed chirpstack applicationID since there will always only be one.

* Split multicast in two entities so it's easier to expand later. Made a new entity called lorawanMulticastDefinition which will contain the informations about a lorawan multicast

* made functionality so devices now will be added to chirpstack if they are a lorawan device. Also made the update functionality, so a device will be removed if it's not a part of the new multicast

* Send message. Possible to get current message queue and to overwrite it

* Made validation for service profile. Devices should only be added to multicast if they alle have same service profile.

* PR changes

* PR changes - fixed pagination for multicast

* PR Changes

* PR Changes

* Pr changes

Co-authored-by: August Andersen <[email protected]>

* Db migrations (#133)

* Made migrations. Now it's nessesary to add migrations when changes are made in db.

The command - npm run typeorm migration:generate -- -n <migrationName> - will generate a migration file if changes are made compared to the db.

When you launch the app, a migration:run command will be called. This will apply the newly migration.

If you want to revert a migration, npm run typeorm migration:revert can be called. It will revert the latest migration.

If you are in doubt which migrations has been called or not, you can write npm run typeorm migration:show. This will show you the pending/fulfilled migrations.

* Since migrations are made in prestart, no need to check on dist.

* PR Changes

* PR changes

Co-authored-by: August Andersen <[email protected]>

* Migrations changes in ormconfig file to make migrations possible in test environment

* Initial migration (#134)

* Initial migration

* Fix proper linting ignore of migrations

* Changed ormconfig.ts to .js so dist folder is created correctly.

Minor changes in package.json.
Removed multicast from initialmigration and made a seperate migration with multicast.

Co-authored-by: augusthjerrild <[email protected]>

* Feature/1220 api key (#136)

* Init api key auth with hardcoded keys

* Added TODOs. Throw 401 if api key is invalid

* Fix roles metadata not set on class controller

* Fetch api keys and sort. Prepare for create and update

* Api key fetch and create done

* Cleanup api key flow. Remove update flow for now

* Validate api key access

* Works - typeerror when building

* Fixed circular dependency error

* Added API guard to relevant controllers

* Fix indentation. Delete unused auth api key request

Co-authored-by: Aram Al-Sabti <[email protected]>
Co-authored-by: nlg <[email protected]>

* Fix roles in controllers where it was set on the whole class (#139)

* Edit API keys (#138)

* Add option for editing API key

* Fix API keys with admin not having write access

* Edit API key PR

* Clean up API key

* CVE-2019-18413. Patch for potential SQL injections (#137)

* CVE-2019-18413. Patch for potential SQL injections

* Fix request 400 on get applications by permission

* Spell organization with British English ("z")

* Simplified migration names

* Optimize chirpstack calls when fetching devices (#143)

* FIWARE datatarget (#141)

* Fiware DataTarget Support

* Migration for Fiware Datatarget

* Fixing incorrect log message

* PR Fixes

* Optimize bulk import and the load on chirpstack (#140)

* Adjust eslint

* Modify bulk import create to take batches. Update missing

* Remove restriction on devices belonging to the same application

* Optimize chirpstack calls. Init updatemany endpoint.

* Implement updateMany and cleanup

* Fix device model not set. Cleanup code. Add comments

* Refactor iot device helpers

* Make device model error code more specific

* Added comment every time invalid devices are filtered

* Fixed issue when creating new IoT device with no device model

* Fixed Fiware datatarget headers declarations and corresponding unit tests (#144)

Co-authored-by: August Andersen <[email protected]>
Co-authored-by: Aram Al-Sabti <[email protected]>
Co-authored-by: nlg <[email protected]>
Co-authored-by: Bartek <[email protected]>
  • Loading branch information
5 people authored Feb 22, 2022
1 parent ba70c7f commit 12485b4
Show file tree
Hide file tree
Showing 122 changed files with 3,506 additions and 389 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ node_modules
dist
# don't lint nyc coverage output
coverage
src/migration/
.eslintrc.js
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ module.exports = {
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-floating-promises": "warn",
"max-lines-per-function": ["error", 80],
"max-lines-per-function": ["warn", 40],
"max-lines-per-function": ["warn", 55],
},
overrides: [
{
Expand Down
15 changes: 15 additions & 0 deletions ormconfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
"type": "postgres",
"host": process.env.DATABASE_HOSTNAME || "host.docker.internal",
"port": parseInt(process.env.DATABASE_PORT, 10) || 5433,
"username": process.env.DATABASE_USERNAME || "os2iot",
"password": process.env.DATABASE_PASSWORD || "toi2so",
"database": "os2iot",
"synchronize": false,
"logging": false,
"entities": ["src/entities/*.ts"],
"migrations": ["src/migration/*.ts"],
"cli": {
"migrationsDir": "src/migration"
}
}
11 changes: 0 additions & 11 deletions ormconfig.json

This file was deleted.

78 changes: 44 additions & 34 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 12 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
"scripts": {
"prebuild": "rimraf dist",
"build": "nest build",
"generate-migration": "npm run typeorm migration:generate -- -n",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"prestart": "npm run run-migrations",
"prestart:debug": "npm run run-migrations",
"prestart:dev": "npm run run-migrations",
"prestart:prod": "npm run run-migrations",
"run-migrations": "npm run typeorm migration:run",
"start": "nest start",
"start:dev": "nest start --watch",
"start:debug": "nest start --debug --watch",
Expand All @@ -19,7 +25,7 @@
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./jest-e2e.js --detectOpenHandles --colors",
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ./ormconfig.json",
"typeorm": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ./ormconfig.js",
"typeorm-e2e": "ts-node -r tsconfig-paths/register ./node_modules/typeorm/cli.js --config ./ormconfig-e2e.json"
},
"dependencies": {
Expand All @@ -30,7 +36,7 @@
"@nestjs/passport": "^7.1.5",
"@nestjs/platform-express": "^7.6.1",
"@nestjs/schedule": "^0.4.1",
"@nestjs/swagger": "^4.7.6",
"@nestjs/swagger": "^4.8.2",
"@nestjs/typeorm": "^7.1.5",
"@types/bcryptjs": "^2.4.2",
"@types/geojson": "^7946.0.7",
Expand All @@ -42,8 +48,8 @@
"axios-cache-adapter": "^2.5.0",
"bcryptjs": "^2.4.3",
"bluebird": "^3.7.2",
"class-transformer": "^0.3.1",
"class-validator": "^0.12.2",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"compression": "^1.7.4",
"cookie-parser": "^1.4.5",
"kafkajs": "^1.15.0",
Expand All @@ -52,6 +58,7 @@
"nestjs-pino": "^1.3.0",
"njwt": "^1.0.0",
"passport": "^0.4.1",
"passport-headerapikey": "^1.2.2",
"passport-jwt": "^4.0.0",
"passport-local": "^1.0.0",
"passport-saml": "^1.3.5",
Expand All @@ -78,6 +85,7 @@
"@types/passport-jwt": "^3.0.3",
"@types/passport-local": "^1.0.33",
"@types/supertest": "^2.0.10",
"@types/validator": "^13.7.1",
"@typescript-eslint/eslint-plugin": "^4.10.0",
"@typescript-eslint/parser": "^4.10.0",
"eslint": "^7.15.0",
Expand Down
6 changes: 6 additions & 0 deletions src/auth/api-key-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { ApiKeyStrategyName } from "./constants";

@Injectable()
export class ApiKeyAuthGuard extends AuthGuard(ApiKeyStrategyName) {}
56 changes: 56 additions & 0 deletions src/auth/api-key.strategy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { AuthenticatedUser } from "@dto/internal/authenticated-user";
import { ErrorCodes } from "@enum/error-codes.enum";
import { Injectable, UnauthorizedException } from "@nestjs/common";
import { PassportStrategy } from "@nestjs/passport";
import { AuthService } from "@services/user-management/auth.service";
import { PermissionService } from "@services/user-management/permission.service";
import { HeaderAPIKeyStrategy } from "passport-headerapikey";
import { ApiKeyHeader, ApiKeyStrategyName, HeaderApiVerifiedCallback } from "./constants";

const passReqToCallback = false;

@Injectable()
export class ApiKeyStrategy extends PassportStrategy(
HeaderAPIKeyStrategy,
ApiKeyStrategyName
) {
constructor(
private authService: AuthService,
private permissionService: PermissionService
) {
super(
{
header: ApiKeyHeader,
prefix: "",
},
passReqToCallback
);
}

async validate(
apiKey: string,
_done: HeaderApiVerifiedCallback
): Promise<AuthenticatedUser> {
const apiKeyDb = await this.authService.validateApiKey(apiKey);
if (!apiKeyDb) {
throw new UnauthorizedException(ErrorCodes.ApiKeyAuthFailed);
}

// Get the permissions and the UserID from the API Key instead of the user
const permissions = await this.permissionService.findPermissionGroupedByLevelForApiKey(
apiKeyDb.id
);

// const permissions = dbApiKey.permissions as Permission[];
const userId = apiKeyDb.systemUser.id;

// Set the permissions and the userId on the returned user
const user: AuthenticatedUser = {
userId,
username: apiKeyDb.systemUser.name,
permissions,
};

return user;
}
}
11 changes: 11 additions & 0 deletions src/auth/compose-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { ApiKeyStrategyName, JwtStrategyName } from "./constants";

@Injectable()
/**
* Let authentication go through a chain of strategies. The first to succeed, redirect, or error will halt the chain
* If a strategy fails (not errors! Ex. JWT token wasn't valid), then authentication proceeds to the next strategy.
* Source: https://docs.nestjs.com/security/authentication#extending-guards
*/
export class ComposeAuthGuard extends AuthGuard([JwtStrategyName, ApiKeyStrategyName]) {}
13 changes: 13 additions & 0 deletions src/auth/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { AuthenticatedUser } from "@dto/internal/authenticated-user";

export type HeaderApiVerifiedCallback = (
err: Error | null,
user?: AuthenticatedUser,
info?: Record<string, unknown>
) => void;

export const ApiKeyStrategyName = "api-key";
export const ApiKeyHeader = "X-API-KEY";
export const LocalStrategyName = "local";
export const JwtStrategyName = "jwt";
export const RolesMetaData = "roles";
3 changes: 2 additions & 1 deletion src/auth/jwt-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { JwtStrategyName } from "./constants";

@Injectable()
export class JwtAuthGuard extends AuthGuard("jwt") {}
export class JwtAuthGuard extends AuthGuard(JwtStrategyName) {}
11 changes: 6 additions & 5 deletions src/auth/jwt.strategy.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { AuthenticatedUser } from "@dto/internal/authenticated-user";
import { JwtPayloadDto } from "@entities/dto/internal/jwt-payload.dto";
import { Injectable, Logger, UnauthorizedException } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { PassportStrategy } from "@nestjs/passport";
import { ExtractJwt, Strategy } from "passport-jwt";

import { AuthenticatedUser } from "@dto/internal/authenticated-user";
import { JwtPayloadDto } from "@entities/dto/internal/jwt-payload.dto";
import { PermissionService } from "@services/user-management/permission.service";
import { UserService } from "@services/user-management/user.service";
import { ExtractJwt, Strategy } from "passport-jwt";
import { JwtStrategyName } from "./constants";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
export class JwtStrategy extends PassportStrategy(Strategy, JwtStrategyName) {
constructor(
private permissionService: PermissionService,
private userService: UserService,
private configService: ConfigService
) {
super({
// Configure the strategy to look for the JWT token in the Authorization header
jwtFromRequest: ExtractJwt.fromExtractors([
ExtractJwt.fromAuthHeaderAsBearerToken(),
ExtractJwt.fromUrlQueryParameter("secret_token"),
Expand Down
3 changes: 2 additions & 1 deletion src/auth/local-auth.guard.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { LocalStrategyName } from "./constants";

@Injectable()
export class LocalAuthGuard extends AuthGuard("local") {}
export class LocalAuthGuard extends AuthGuard(LocalStrategyName) {}
Loading

0 comments on commit 12485b4

Please sign in to comment.