Browse Source

fix: jwt strategy init

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5444/head
Pranav C 2 years ago
parent
commit
7f7eb73fa2
  1. 31
      packages/nocodb-nest/src/app.module.ts
  2. 49
      packages/nocodb-nest/src/db/BaseModelSqlv2.ts
  3. 110
      packages/nocodb-nest/src/models/Model.ts
  4. 8
      packages/nocodb-nest/src/modules/auth/auth.module.ts
  5. 19
      packages/nocodb-nest/src/modules/global/global.module.ts
  6. 8
      packages/nocodb-nest/src/modules/users/users.controller.ts
  7. 13
      packages/nocodb-nest/src/modules/users/users.module.ts
  8. 8
      packages/nocodb-nest/src/modules/users/users.service.ts
  9. 24
      packages/nocodb-nest/src/strategies/jwt.strategy.ts

31
packages/nocodb-nest/src/app.module.ts

@ -1,5 +1,6 @@
import { Module, RequestMethod } from '@nestjs/common';
import { APP_FILTER } from '@nestjs/core';
import { ExtractJwt } from 'passport-jwt';
import { Connection } from './connection/connection';
import { GlobalExceptionFilter } from './filters/global-exception/global-exception.filter';
import { GlobalMiddleware } from './middlewares/global/global.middleware';
@ -7,6 +8,7 @@ import { AuthModule } from './modules/auth/auth.module';
import { ExtractProjectIdMiddleware } from './middlewares/extract-project-id/extract-project-id.middleware';
import { UsersModule } from './modules/users/users.module';
import { MetaService } from './meta/meta.service';
import { UsersService } from './modules/users/users.service';
import { UtilsModule } from './modules/utils/utils.module';
import { ProjectsModule } from './modules/projects/projects.module';
import Noco from './Noco';
@ -47,17 +49,38 @@ import { ImportModule } from './modules/import/import.module';
import { CachesModule } from './modules/caches/caches.module';
import { TestModule } from './modules/test/test.module';
import { PluginsModule } from './modules/plugins/plugins.module';
import { GlobalModule } from './modules/global/global.module';
import NcConfigFactory from './utils/NcConfigFactory'
import NcUpgrader from './version-upgrader/NcUpgrader';
import type {
MiddlewareConsumer,
OnApplicationBootstrap,
Provider,
} from '@nestjs/common';
import { GlobalModule } from './modules/global/global.module';
import NcUpgrader from './version-upgrader/NcUpgrader';
export const JwtStrategyProvider: Provider = {
provide: JwtStrategy,
useFactory: async (usersService: UsersService) => {
const config = await NcConfigFactory.make()
const options = {
// ignoreExpiration: false,
jwtFromRequest: ExtractJwt.fromHeader('xc-auth'),
expiresIn: '10h',
passReqToCallback: true,
secretOrKey: config.auth.jwt.secret,
...config.auth.jwt.options,
};
return new JwtStrategy(options, usersService);
},
inject: [UsersService],
};
@Module({
imports: [
GlobalModule,
AuthModule,
// AuthModule,
UsersModule,
UtilsModule,
ProjectsModule,
@ -104,7 +127,7 @@ import NcUpgrader from './version-upgrader/NcUpgrader';
provide: APP_FILTER,
useClass: GlobalExceptionFilter,
},
JwtStrategy,
JwtStrategyProvider,
ExtractProjectIdMiddleware,
],
})

49
packages/nocodb-nest/src/db/BaseModelSqlv2.ts

@ -50,6 +50,8 @@ import genRollupSelectv2 from './genRollupSelectv2';
import conditionV2 from './conditionV2';
import sortV2 from './sortV2';
import { customValidators } from './util/customValidators';
import type LookupColumn from '../../../nocodb/src/lib/models/LookupColumn';
import type { XKnex } from '../../../nocodb/src/lib/db/sql-data-mapper';
import type {
XcFilter,
XcFilterWithAlias,
@ -118,7 +120,7 @@ function checkColumnRequired(
* @classdesc Base class for models
*/
class BaseModelSqlv2 {
protected dbDriver: Knex;
protected dbDriver: XKnex;
protected model: Model;
protected viewId: string;
private _proto: any;
@ -1404,7 +1406,6 @@ class BaseModelSqlv2 {
return [];
}
});
const self: BaseModelSqlv2 = this;
proto[column.title] = async function (args): Promise<any> {
@ -1891,7 +1892,7 @@ class BaseModelSqlv2 {
await this.execAndParse(query);
const newData = await this.readByPk(id);
await this.afterUpdate(prevData, newData, trx, cookie);
await this.afterUpdate(prevData, newData, trx, cookie, updateObj);
return newData;
} catch (e) {
console.log(e);
@ -2323,7 +2324,7 @@ class BaseModelSqlv2 {
op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.INSERT,
description: DOMPurify.sanitize(
`${id} inserted into ${this.model.title}`,
`Record with ID ${id} has been inserted into Table ${this.model.title}`,
),
// details: JSON.stringify(data),
ip: req?.clientIp,
@ -2349,7 +2350,9 @@ class BaseModelSqlv2 {
op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.BULK_UPDATE,
description: DOMPurify.sanitize(
`${noOfUpdatedRecords} records bulk updated in ${this.model.title}`,
`${noOfUpdatedRecords} ${
noOfUpdatedRecords > 1 ? 'records have' : 'record has'
} been bulk updated in ${this.model.title}`,
),
// details: JSON.stringify(data),
ip: req?.clientIp,
@ -2374,7 +2377,9 @@ class BaseModelSqlv2 {
op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.BULK_DELETE,
description: DOMPurify.sanitize(
`${noOfDeletedRecords} records bulk deleted in ${this.model.title}`,
`${noOfDeletedRecords} ${
noOfDeletedRecords > 1 ? 'records have' : 'record has'
} been bulk deleted in ${this.model.title}`,
),
// details: JSON.stringify(data),
ip: req?.clientIp,
@ -2390,7 +2395,9 @@ class BaseModelSqlv2 {
op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.BULK_INSERT,
description: DOMPurify.sanitize(
`${data.length} records bulk inserted into ${this.model.title}`,
`${data.length} ${
data.length > 1 ? 'records have' : 'record has'
} been bulk inserted in ${this.model.title}`,
),
// details: JSON.stringify(data),
ip: req?.clientIp,
@ -2415,15 +2422,31 @@ class BaseModelSqlv2 {
newData: any,
_trx: any,
req,
updateObj?: Record<string, any>,
): Promise<void> {
const id = this._extractPksValues(newData);
let desc = `Record with ID ${id} has been updated in Table ${this.model.title}.`;
if (updateObj) {
updateObj = await this.model.mapColumnToAlias(updateObj);
for (const k of Object.keys(updateObj)) {
const prevValue =
typeof prevData[k] === 'object'
? JSON.stringify(prevData[k])
: prevData[k];
const newValue =
typeof newData[k] === 'object'
? JSON.stringify(newData[k])
: newData[k];
desc += `\n`;
desc += `Column "${k}" got changed from "${prevValue}" to "${newValue}"`;
}
}
await Audit.insert({
fk_model_id: this.model.id,
row_id: id,
op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.UPDATE,
description: DOMPurify.sanitize(`${id} updated in ${this.model.title}`),
description: DOMPurify.sanitize(desc),
// details: JSON.stringify(data),
ip: req?.clientIp,
user: req?.user?.email,
@ -2451,7 +2474,9 @@ class BaseModelSqlv2 {
row_id: id,
op_type: AuditOperationTypes.DATA,
op_sub_type: AuditOperationSubTypes.DELETE,
description: DOMPurify.sanitize(`${id} deleted from ${this.model.title}`),
description: DOMPurify.sanitize(
`Record with ID ${id} has been deleted in Table ${this.model.title}`,
),
// details: JSON.stringify(data),
ip: req?.clientIp,
user: req?.user?.email,
@ -2722,7 +2747,7 @@ class BaseModelSqlv2 {
op_sub_type: AuditOperationSubTypes.LINK_RECORD,
row_id: rowId,
description: DOMPurify.sanitize(
`Record [id:${childId}] record linked with record [id:${rowId}] record in ${this.model.title}`,
`Record [id:${childId}] has been linked with record [id:${rowId}] in ${this.model.title}`,
),
// details: JSON.stringify(data),
ip: req?.clientIp,
@ -2824,7 +2849,7 @@ class BaseModelSqlv2 {
op_sub_type: AuditOperationSubTypes.UNLINK_RECORD,
row_id: rowId,
description: DOMPurify.sanitize(
`Record [id:${childId}] record unlinked with record [id:${rowId}] record in ${this.model.title}`,
`Record [id:${childId}] has been unlinked with record [id:${rowId}] in ${this.model.title}`,
),
// details: JSON.stringify(data),
ip: req?.clientIp,

110
packages/nocodb-nest/src/models/Model.ts

@ -57,7 +57,7 @@ export default class Model implements TableType {
{
fk_model_id: this.id,
},
ncMeta,
ncMeta
);
return this.columns;
}
@ -94,7 +94,7 @@ export default class Model implements TableType {
mm?: BoolType;
type?: ModelTypes;
},
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
const insertObj = extractProps(model, [
'table_name',
@ -113,7 +113,7 @@ export default class Model implements TableType {
{
project_id: projectId,
base_id: baseId,
},
}
);
}
@ -125,13 +125,13 @@ export default class Model implements TableType {
projectId,
baseId,
MetaTable.MODELS,
insertObj,
insertObj
);
await NocoCache.appendToList(
CacheScope.MODEL,
[projectId],
`${CacheScope.MODEL}:${id}`,
`${CacheScope.MODEL}:${id}`
);
const view = await View.insert(
@ -141,7 +141,7 @@ export default class Model implements TableType {
is_default: true,
type: ViewTypes.GRID,
},
ncMeta,
ncMeta
);
for (const column of model?.columns || []) {
@ -159,7 +159,7 @@ export default class Model implements TableType {
project_id: string;
base_id: string;
},
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
): Promise<Model[]> {
let modelList = [];
if (base_id) {
@ -176,7 +176,7 @@ export default class Model implements TableType {
orderBy: {
order: 'asc',
},
},
}
);
// parse meta of each model
@ -188,7 +188,7 @@ export default class Model implements TableType {
await NocoCache.setList(
CacheScope.MODEL,
[project_id, base_id],
modelList,
modelList
);
} else {
await NocoCache.setList(CacheScope.MODEL, [project_id], modelList);
@ -197,7 +197,7 @@ export default class Model implements TableType {
modelList.sort(
(a, b) =>
(a.order != null ? a.order : Infinity) -
(b.order != null ? b.order : Infinity),
(b.order != null ? b.order : Infinity)
);
return modelList.map((m) => new Model(m));
}
@ -210,7 +210,7 @@ export default class Model implements TableType {
project_id: string;
db_alias: string;
},
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
): Promise<Model[]> {
let modelList = await NocoCache.getList(CacheScope.MODEL, [
project_id,
@ -220,7 +220,7 @@ export default class Model implements TableType {
modelList = await ncMeta.metaList2(
project_id,
db_alias,
MetaTable.MODELS,
MetaTable.MODELS
);
// parse meta of each model
@ -244,7 +244,7 @@ export default class Model implements TableType {
id &&
(await NocoCache.get(
`${CacheScope.MODEL}:${id}`,
CacheGetType.TYPE_OBJECT,
CacheGetType.TYPE_OBJECT
));
if (!modelData) {
modelData = await ncMeta.metaGet2(null, null, MetaTable.MODELS, id);
@ -267,14 +267,14 @@ export default class Model implements TableType {
| {
id?: string;
},
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
): Promise<Model> {
const k = 'id' in args ? args?.id : args;
let modelData =
k &&
(await NocoCache.get(
`${CacheScope.MODEL}:${k}`,
CacheGetType.TYPE_OBJECT,
CacheGetType.TYPE_OBJECT
));
if (!modelData) {
modelData = await ncMeta.metaGet2(null, null, MetaTable.MODELS, k);
@ -295,13 +295,13 @@ export default class Model implements TableType {
table_name?: string;
id?: string;
},
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
): Promise<Model> {
let modelData =
id &&
(await NocoCache.get(
`${CacheScope.MODEL}:${id}`,
CacheGetType.TYPE_OBJECT,
CacheGetType.TYPE_OBJECT
));
if (!modelData) {
modelData = await ncMeta.metaGet2(
@ -310,7 +310,7 @@ export default class Model implements TableType {
MetaTable.MODELS,
id || {
table_name,
},
}
);
modelData.meta = parseMetaProp(modelData);
await NocoCache.set(`${CacheScope.MODEL}:${modelData.id}`, modelData);
@ -336,7 +336,7 @@ export default class Model implements TableType {
dbDriver: XKnex;
model?: Model;
},
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
): Promise<BaseModelSqlv2> {
const model = args?.model || (await this.get(args.id, ncMeta));
@ -388,7 +388,7 @@ export default class Model implements TableType {
await NocoCache.deepDel(
cacheScopeName,
`${cacheScopeName}:${col.id}`,
CacheDelDirection.CHILD_TO_PARENT,
CacheDelDirection.CHILD_TO_PARENT
);
}
}
@ -402,14 +402,14 @@ export default class Model implements TableType {
condition: {
fk_related_model_id: this.id,
},
},
}
);
for (const col of leftOverColumns) {
await NocoCache.deepDel(
CacheScope.COL_RELATION,
`${CacheScope.COL_RELATION}:${col.fk_column_id}`,
CacheDelDirection.CHILD_TO_PARENT,
CacheDelDirection.CHILD_TO_PARENT
);
}
@ -421,7 +421,7 @@ export default class Model implements TableType {
await NocoCache.deepDel(
CacheScope.COLUMN,
`${CacheScope.COLUMN}:${this.id}`,
CacheDelDirection.CHILD_TO_PARENT,
CacheDelDirection.CHILD_TO_PARENT
);
await ncMeta.metaDelete(null, null, MetaTable.COLUMNS, {
fk_model_id: this.id,
@ -430,7 +430,7 @@ export default class Model implements TableType {
await NocoCache.deepDel(
CacheScope.MODEL,
`${CacheScope.MODEL}:${this.id}`,
CacheDelDirection.CHILD_TO_PARENT,
CacheDelDirection.CHILD_TO_PARENT
);
await ncMeta.metaDelete(null, null, MetaTable.MODELS, this.id);
@ -457,11 +457,29 @@ export default class Model implements TableType {
return insertObj;
}
async mapColumnToAlias(data) {
const res = {};
for (const col of await this.getColumns()) {
if (isVirtualCol(col)) continue;
let val =
data?.[col.title] !== undefined
? data?.[col.title]
: data?.[col.column_name];
if (val !== undefined) {
if (col.uidt === UITypes.Attachment && typeof val !== 'string') {
val = JSON.stringify(val);
}
res[sanitize(col.title)] = val;
}
}
return res;
}
static async updateAliasAndTableName(
tableId,
title: string,
table_name: string,
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
if (!title) {
NcError.badRequest("Missing 'title' property in body");
@ -488,7 +506,7 @@ export default class Model implements TableType {
title,
table_name,
},
tableId,
tableId
);
}
@ -510,7 +528,7 @@ export default class Model implements TableType {
{
mm: isMm,
},
tableId,
tableId
);
}
@ -535,7 +553,7 @@ export default class Model implements TableType {
static async updateOrder(
tableId: string,
order: number,
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
@ -553,14 +571,14 @@ export default class Model implements TableType {
{
order,
},
tableId,
tableId
);
}
static async updatePrimaryColumn(
tableId: string,
columnId: string,
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
const model = await this.getWithInfo({ id: tableId });
const newPvCol = model.columns.find((c) => c.id === columnId);
@ -585,7 +603,7 @@ export default class Model implements TableType {
{
pv: false,
},
col.id,
col.id
);
}
@ -605,7 +623,7 @@ export default class Model implements TableType {
{
pv: true,
},
newPvCol.id,
newPvCol.id
);
const grid_views_with_column = await ncMeta.metaList2(
@ -616,7 +634,7 @@ export default class Model implements TableType {
condition: {
fk_column_id: newPvCol.id,
},
},
}
);
if (grid_views_with_column.length) {
@ -645,7 +663,7 @@ export default class Model implements TableType {
{
mm: true,
},
id,
id
);
}
@ -659,14 +677,14 @@ export default class Model implements TableType {
base_id?: string;
aliasOrId: string;
},
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
const modelId =
project_id &&
aliasOrId &&
(await NocoCache.get(
`${CacheScope.MODEL}:${project_id}:${aliasOrId}`,
CacheGetType.TYPE_OBJECT,
CacheGetType.TYPE_OBJECT
));
if (!modelId) {
const model = base_id
@ -689,7 +707,7 @@ export default class Model implements TableType {
},
},
],
},
}
)
: await ncMeta.metaGet2(
null,
@ -710,12 +728,12 @@ export default class Model implements TableType {
},
},
],
},
}
);
if (model) {
await NocoCache.set(
`${CacheScope.MODEL}:${project_id}:${aliasOrId}`,
model.id,
model.id
);
await NocoCache.set(`${CacheScope.MODEL}:${model.id}`, model);
}
@ -731,7 +749,7 @@ export default class Model implements TableType {
base_id,
exclude_id,
}: { table_name; project_id; base_id; exclude_id? },
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
return !(await ncMeta.metaGet2(
project_id,
@ -741,7 +759,7 @@ export default class Model implements TableType {
table_name,
},
null,
exclude_id && { id: { neq: exclude_id } },
exclude_id && { id: { neq: exclude_id } }
));
}
@ -752,7 +770,7 @@ export default class Model implements TableType {
base_id,
exclude_id,
}: { title; project_id; base_id; exclude_id? },
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
return !(await ncMeta.metaGet2(
project_id,
@ -762,14 +780,14 @@ export default class Model implements TableType {
title,
},
null,
exclude_id && { id: { neq: exclude_id } },
exclude_id && { id: { neq: exclude_id } }
));
}
async getAliasColObjMap() {
return (await this.getColumns()).reduce(
(sortAgg, c) => ({ ...sortAgg, [c.title]: c }),
{},
{}
);
}
@ -777,7 +795,7 @@ export default class Model implements TableType {
static async updateMeta(
tableId: string,
meta: string | Record<string, any>,
ncMeta = Noco.ncMeta,
ncMeta = Noco.ncMeta
) {
// get existing cache
const key = `${CacheScope.MODEL}:${tableId}`;
@ -797,7 +815,7 @@ export default class Model implements TableType {
{
meta: typeof meta === 'object' ? JSON.stringify(meta) : meta,
},
tableId,
tableId
);
}
}

8
packages/nocodb-nest/src/modules/auth/auth.module.ts

@ -5,18 +5,12 @@ import { LocalStrategy } from '../../strategies/local.strategy';
import { UsersModule } from '../users/users.module';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
import { jwtConstants } from './constants';
@Module({
controllers: [AuthController],
imports: [
UsersModule,
PassportModule,
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '10h' },
}),
PassportModule
],
providers: [AuthService, LocalStrategy],
})

19
packages/nocodb-nest/src/modules/global/global.module.ts

@ -1,16 +1,23 @@
import { Global, Module } from '@nestjs/common'
import { JwtModule, JwtService } from '@nestjs/jwt'
import { Connection } from '../../connection/connection'
import { MetaService } from '../../meta/meta.service'
import { jwtConstants } from '../auth/constants'
@Global()
@Module({
providers:[
imports: [
],
providers: [
Connection,
MetaService
MetaService,
],
exports: [
exports: [
Connection,
MetaService
]
MetaService,
// JwtService,
],
})
export class GlobalModule {}
export class GlobalModule {
}

8
packages/nocodb-nest/src/modules/users/users.controller.ts

@ -31,12 +31,14 @@ export class UsersController {
'/api/v1/db/auth/user/signup',
'/api/v1/auth/user/signup',
])
async signup(@Request() req: any, @Request() res: any): Promise<any> {
return await this.usersService.signup({
async signup(@Request() req: any, @Response() res: any): Promise<any> {
res.json(
await this.usersService.signup({
body: req.body,
req,
res,
});
}),
);
}
@Post([

13
packages/nocodb-nest/src/modules/users/users.module.ts

@ -1,13 +1,20 @@
import { Module } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { JwtModule } from '@nestjs/jwt';
import { jwtConstants } from '../auth/constants';
import { GlobalModule } from '../global/global.module';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';
@Module({
imports: [GlobalModule],
imports: [
GlobalModule,
JwtModule.register({
secret: jwtConstants.secret,
signOptions: { expiresIn: '10h' },
}),
],
controllers: [UsersController],
providers: [UsersService, JwtService],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}

8
packages/nocodb-nest/src/modules/users/users.service.ts

@ -459,7 +459,6 @@ export class UsersService {
'Warning : `mailSend` failed, Please configure emailClient configuration.',
);
}
await promisify((param.req as any).login.bind(param.req))(user);
const refreshToken = randomTokenString();
@ -468,9 +467,8 @@ export class UsersService {
email: user.email,
});
setTokenCookie(param.res, refreshToken);
user = (param.req as any).user;
setTokenCookie(param.res, refreshToken);
await Audit.insert({
op_type: 'AUTHENTICATION',
@ -481,7 +479,7 @@ export class UsersService {
});
return {
token: genJwt(user, Noco.getConfig()),
token: this.login(user),
} as any;
}
@ -490,7 +488,7 @@ export class UsersService {
delete user.salt;
const payload = user;
return {
token: this.jwtService.sign(payload),
token: genJwt(user, Noco.getConfig()), //this.jwtService.sign(payload),
};
}
}

24
packages/nocodb-nest/src/strategies/jwt.strategy.ts

@ -4,22 +4,28 @@ import { ExtractJwt, Strategy } from 'passport-jwt';
import { OrgUserRoles } from '../../../nocodb-sdk';
import NocoCache from '../cache/NocoCache';
import { ProjectUser, User } from '../models';
import { genJwt } from '../modules/users/helpers'
import Noco from '../Noco'
import extractRolesObj from '../utils/extractRolesObj';
import { CacheGetType, CacheScope } from '../utils/globals';
import { jwtConstants } from '../modules/auth/constants';
import { UsersService } from '../modules/users/users.service';
import NcConfigFactory from '../utils/NcConfigFactory'
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
constructor(private userService: UsersService) {
super({
// ignoreExpiration: false,
jwtFromRequest: ExtractJwt.fromHeader('xc-auth'),
secretOrKey: jwtConstants.secret,
expiresIn: '10h',
passReqToCallback: true,
});
constructor(options, private userService: UsersService, ) {
super(
options
)
// {
// // ignoreExpiration: false,
// jwtFromRequest: ExtractJwt.fromHeader('xc-auth'),
// expiresIn: '10h',
// passReqToCallback: true,
// secretOrKey: process.env.NC_AUTH_JWT_SECRET ?? 'temporary-key'
//
// });
}
async validate(req: any, jwtPayload: any) {

Loading…
Cancel
Save