Browse Source

Merge branch 'develop' into nc-fix/swagger-base-pw

pull/9543/head
Raju Udava 2 months ago
parent
commit
6efdd79d4b
  1. 3
      packages/nc-gui/components/account/Token.vue
  2. 2
      packages/nc-gui/components/tabs/auth/ApiTokenManagement.vue
  3. 8
      packages/nocodb/src/controllers/api-tokens.controller.ts
  4. 6
      packages/nocodb/src/controllers/org-tokens.controller.ts
  5. 16
      packages/nocodb/src/models/ApiToken.ts
  6. 243
      packages/nocodb/src/schema/swagger-v2.json
  7. 14
      packages/nocodb/src/schema/swagger.json
  8. 8
      packages/nocodb/src/services/api-tokens.service.ts
  9. 2
      packages/nocodb/src/services/app-hooks/interfaces.ts
  10. 8
      packages/nocodb/src/services/org-tokens.service.ts

3
packages/nc-gui/components/account/Token.vue

@ -140,7 +140,8 @@ const isValidTokenName = ref(false)
const deleteToken = async (token: string): Promise<void> => {
try {
await api.orgTokens.delete(token)
const id = allTokens.value.find((t) => t.token === token)?.id
await api.orgTokens.delete(id)
// message.success(t('msg.success.tokenDeleted'))
await loadTokens()

2
packages/nc-gui/components/tabs/auth/ApiTokenManagement.vue

@ -67,7 +67,7 @@ const deleteToken = async () => {
try {
if (!base.value?.id || !selectedTokenData.value.token) return
await $api.apiToken.delete(base.value.id, selectedTokenData.value.token)
await $api.apiToken.delete(base.value.id, selectedTokenData.value.id)
// Token deleted successfully
message.success(t('msg.success.tokenDeleted'))

8
packages/nocodb/src/controllers/api-tokens.controller.ts

@ -47,13 +47,13 @@ export class ApiTokensController {
}
@Delete([
'/api/v1/db/meta/projects/:baseId/api-tokens/:token',
'/api/v2/meta/bases/:baseId/api-tokens/:token',
'/api/v1/db/meta/projects/:baseId/api-tokens/:tokenId',
'/api/v2/meta/bases/:baseId/api-tokens/:tokenId',
])
@Acl('baseApiTokenDelete')
async apiTokenDelete(@Req() req: NcRequest, @Param('token') token: string) {
async apiTokenDelete(@Req() req: NcRequest, @Param('tokenId') tokenId: string) {
return await this.apiTokensService.apiTokenDelete({
token,
tokenId,
user: req['user'],
req,
});

6
packages/nocodb/src/controllers/org-tokens.controller.ts

@ -55,15 +55,15 @@ export class OrgTokensController {
});
}
@Delete('/api/v1/tokens/:token')
@Delete('/api/v1/tokens/:tokenId')
@Acl('apiTokenDelete', {
scope: 'org',
// allowedRoles: [OrgUserRoles.SUPER],
blockApiTokenAccess: true,
})
async apiTokenDelete(@Req() req: NcRequest, @Param('token') token: string) {
async apiTokenDelete(@Req() req: NcRequest, @Param('tokenId') tokenId: string) {
await this.orgTokensService.apiTokenDelete({
token,
tokenId,
user: req['user'],
req,
});

16
packages/nocodb/src/models/ApiToken.ts

@ -66,16 +66,17 @@ export default class ApiToken implements ApiTokenType {
return tokens?.map((t) => new ApiToken(t));
}
static async delete(token, ncMeta = Noco.ncMeta) {
static async delete(tokenId: string, ncMeta = Noco.ncMeta) {
const tokenData = await this.get(tokenId, ncMeta);
await NocoCache.deepDel(
`${CacheScope.API_TOKEN}:${token}`,
`${CacheScope.API_TOKEN}:${tokenData.id}`,
CacheDelDirection.CHILD_TO_PARENT,
);
return await ncMeta.metaDelete(
RootScopes.ROOT,
RootScopes.ROOT,
MetaTable.API_TOKENS,
{ token },
tokenId,
);
}
@ -165,4 +166,13 @@ export default class ApiToken implements ApiTokenType {
return queryBuilder;
}
static async get(tokenId: string, ncMeta = Noco.ncMeta) {
return await ncMeta.metaGet(
RootScopes.ROOT,
RootScopes.ROOT,
MetaTable.API_TOKENS,
tokenId,
);
}
}

243
packages/nocodb/src/schema/swagger-v2.json

@ -242,7 +242,7 @@
"tags": [
"Workspace base", "Bases"
],
"description": "This API fetches list of bases associated with the specified workspace ID. The workspace ID must be provided in the path as a required parameter. The API returns a list in JSON format, containing metadata and configuration for each base.",
"description": "This API fetches list of bases associated with the specified workspace ID. The workspace ID must be provided in the path as a required parameter. The API returns a list in JSON format, containing metadata and configuration for each base. The API returns a paginated list of bases.\n\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\n\n- `totalRows`: Indicates the total number of bases available in the specified Workspace ID.\n- `page`: Specifies the current page number.\n- `pageSize`: Defaults to 25 and defines the number of base items listed on each page.\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of base records in the dataset.\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of base records in the dataset.",
"parameters": [
{
"$ref": "#/components/parameters/xc-token"
@ -1164,7 +1164,7 @@
"$ref": "#/components/responses/BadRequest"
}
},
"description": "List all users in the given base.",
"description": "This endpoint allows you to list all users (collaborators) within a specified base. The API returns a paginated list of users.\\n\\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\\n\\n- `totalRows`: Indicates the total number of users available in the specified Base ID.\\n- `page`: Specifies the current page number.\\n- `pageSize`: Defaults to 25 and defines the number of user items listed on each page.\\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of user records in the dataset.\\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of user records in the dataset.",
"tags": [
"Auth", "Users"
],
@ -2253,7 +2253,7 @@
"get": {
"summary": "List Sources",
"operationId": "source-list",
"description": "Get base source list",
"description": "This endpoint allows you to list all (data) sources within a specified base. The API returns a paginated list of data sources.\\n\\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\\n\\n- `totalRows`: Indicates the total number of sources available in the specified Base ID.\\n- `page`: Specifies the current page number.\\n- `pageSize`: Defaults to 25 and defines the number of source items listed on each page.\\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of source records in the dataset.\\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of source records in the dataset.",
"parameters": [
{
"$ref": "#/components/parameters/xc-token"
@ -4905,7 +4905,7 @@
"tags": [
"DB View", "Views"
],
"description": "List all views in a given Table.",
"description": "This endpoint allows you to list all views within a specified table. The API returns a paginated list of views.\n\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\n\n- `totalRows`: Indicates the total number of views available in the specified Table ID.\n- `page`: Specifies the current page number.\n- `pageSize`: Defaults to 25 and defines the number of view items listed on each page.\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of view records in the dataset.\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of view records in the dataset.",
"parameters": [
{
"$ref": "#/components/parameters/xc-token"
@ -5214,7 +5214,7 @@
"$ref": "#/components/responses/BadRequest"
}
},
"description": "List all shared views in a given Table",
"description": "This endpoint allows you to list all Shared Views within a specified table. The API returns a paginated list of shared views.\\n\\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\\n\\n- `totalRows`: Indicates the total number of shared views available in the specified Table ID.\\n- `page`: Specifies the current page number.\\n- `pageSize`: Defaults to 25 and defines the number of shared view items listed on each page.\\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of shared view records in the dataset.\\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of shared view records in the dataset.",
"tags": [
"DB View Share", "Shared Views"
],
@ -5657,7 +5657,7 @@
"tags": [
"DB Table Sort", "Sorts"
],
"description": "List all the sort data in a given View",
"description": "This endpoint allows you to list all sorts within a specified view. The API returns a paginated list of sorts.\\n\\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\\n\\n- `totalRows`: Indicates the total number of sorts available in the specified View ID.\\n- `page`: Specifies the current page number.\\n- `pageSize`: Defaults to 25 and defines the number of sort items listed on each page.\\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of sort records in the dataset.\\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of sort records in the dataset.",
"parameters": [
{
"$ref": "#/components/parameters/xc-token"
@ -5926,7 +5926,7 @@
"tags": [
"DB Table Filter", "Filters"
],
"description": "Get the filter data in a given View",
"description": "This endpoint allows you to list all filters within a specified view. The API returns a paginated list of filters.\\n\\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\\n\\n- `totalRows`: Indicates the total number of filters available in the specified View ID.\\n- `page`: Specifies the current page number.\\n- `pageSize`: Defaults to 25 and defines the number of filter items listed on each page.\\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of filter records in the dataset.\\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of filter records in the dataset.",
"parameters": [
{
"$ref": "#/components/parameters/xc-token"
@ -10223,7 +10223,7 @@
"$ref": "#/components/responses/BadRequest"
}
},
"description": "List all hook records in the given Table",
"description": "This endpoint allows you to list all webhooks within a specified table. The API returns a paginated list of webhooks.\\n\\n**Pagination**: The response is paginated by default, with the first page being returned initially. The response includes the following additional information in the `pageInfo` JSON block:\\n\\n- `totalRows`: Indicates the total number of webhooks available in the specified Table ID.\\n- `page`: Specifies the current page number.\\n- `pageSize`: Defaults to 25 and defines the number of webhook items listed on each page.\\n- `isFirstPage`: A boolean value that indicates whether the current page is the first page of webhook records in the dataset.\\n- `isLastPage`: A boolean value that indicates whether the current page is the last page of webhook records in the dataset.",
"parameters": [
{
"$ref": "#/components/parameters/xc-token"
@ -11544,7 +11544,7 @@
}
]
},
"/api/v2/meta/bases/{baseId}/api-tokens/{token}": {
"/api/v2/meta/bases/{baseId}/api-tokens/{tokenId}": {
"delete": {
"summary": "Delete API Token",
"operationId": "api-token-delete",
@ -11594,12 +11594,12 @@
{
"schema": {
"type": "string",
"example": "DYh540o8hbWpUGdarekECKLdN5OhlgCUWutVJYX2"
"example": "DYh540o8hbWp"
},
"name": "token",
"name": "tokenId",
"in": "path",
"required": true,
"description": "API Token"
"description": "API Token ID"
}
]
},
@ -13640,6 +13640,16 @@
"id": "tty21vb01bfr0"
}
},
"BaseMeta": {
"description": "Additional meta during base creation",
"properties": {
"iconColor": {
"description": "Icon color code in hexadecimal format",
"type": "string"
}
},
"type": "object"
},
"BaseReq": {
"description": "Model for Source Request",
"examples": [
@ -16964,10 +16974,197 @@
"description": "Currency settings for this column. Locale defaults to `en-US` and currency code defaults to `USD`",
"properties": {
"currency_locale": {
"type": "string"
"type": "string",
"description": "Currency locale code. Refer https://simplelocalize.io/data/locales/"
},
"currency_code": {
"type": "string"
"type": "string",
"description": "Currency code. Refer https://simplelocalize.io/data/locales/",
"enum": [
"AED",
"AFN",
"ALL",
"AMD",
"ANG",
"AOA",
"ARS",
"AUD",
"AWG",
"AZN",
"BAM",
"BBD",
"BDT",
"BGN",
"BHD",
"BIF",
"BMD",
"BND",
"BOB",
"BOV",
"BRL",
"BSD",
"BTN",
"BWP",
"BYR",
"BZD",
"CAD",
"CDF",
"CHE",
"CHF",
"CHW",
"CLF",
"CLP",
"CNY",
"COP",
"COU",
"CRC",
"CUP",
"CVE",
"CYP",
"CZK",
"DJF",
"DKK",
"DOP",
"DZD",
"EEK",
"EGP",
"ERN",
"ETB",
"EUR",
"FJD",
"FKP",
"GBP",
"GEL",
"GHC",
"GIP",
"GMD",
"GNF",
"GTQ",
"GYD",
"HKD",
"HNL",
"HRK",
"HTG",
"HUF",
"IDR",
"ILS",
"INR",
"IQD",
"IRR",
"ISK",
"JMD",
"JOD",
"JPY",
"KES",
"KGS",
"KHR",
"KMF",
"KPW",
"KRW",
"KWD",
"KYD",
"KZT",
"LAK",
"LBP",
"LKR",
"LRD",
"LSL",
"LTL",
"LVL",
"LYD",
"MAD",
"MDL",
"MGA",
"MKD",
"MMK",
"MNT",
"MOP",
"MRO",
"MTL",
"MUR",
"MVR",
"MWK",
"MXN",
"MXV",
"MYR",
"MZN",
"NAD",
"NGN",
"NIO",
"NOK",
"NPR",
"NZD",
"OMR",
"PAB",
"PEN",
"PGK",
"PHP",
"PKR",
"PLN",
"PYG",
"QAR",
"ROL",
"RON",
"RSD",
"RUB",
"RWF",
"SAR",
"SBD",
"SCR",
"SDD",
"SEK",
"SGD",
"SHP",
"SIT",
"SKK",
"SLL",
"SOS",
"SRD",
"STD",
"SYP",
"SZL",
"THB",
"TJS",
"TMM",
"TND",
"TOP",
"TRY",
"TTD",
"TWD",
"TZS",
"UAH",
"UGX",
"USD",
"USN",
"USS",
"UYU",
"UZS",
"VEB",
"VND",
"VUV",
"WST",
"XAF",
"XAG",
"XAU",
"XBA",
"XBB",
"XBC",
"XBD",
"XCD",
"XDR",
"XFO",
"XFU",
"XOF",
"XPD",
"XPF",
"XPT",
"XTS",
"XXX",
"YER",
"ZAR",
"ZMK",
"ZWD"
]
}
}
},
@ -19129,7 +19326,6 @@
"type": "mysql"
}
],
"color": "#24716E",
"description": "This is my base description",
"title": "My Base"
}
@ -19147,14 +19343,8 @@
"example": "This is my base description",
"type": "string"
},
"color": {
"description": "Primary Theme Color",
"example": "#24716E",
"maxLength": 50,
"type": "string"
},
"meta": {
"$ref": "#/components/schemas/Meta",
"$ref": "#/components/schemas/BaseMeta",
"description": "Base Meta"
}
},
@ -19174,7 +19364,6 @@
},
"examples": [
{
"color": "#24716E",
"meta": null,
"title": "My Base",
"order": 1
@ -19190,12 +19379,6 @@
"minLength": 1,
"type": "string"
},
"color": {
"description": "Primary Theme Color",
"example": "#24716E",
"maxLength": 50,
"type": "string"
},
"order": {
"type": "number",
"description": "The order of the list of projects.",
@ -19203,7 +19386,7 @@
"minimum": 0
},
"meta": {
"$ref": "#/components/schemas/Meta",
"$ref": "#/components/schemas/BaseMeta",
"description": "Base Meta",
"x-stoplight": {
"id": "m05w9sbwqgul3"

14
packages/nocodb/src/schema/swagger.json

@ -819,16 +819,16 @@
"description": "Creat an organisation API token. Access with API tokens will be blocked."
}
},
"/api/v1/tokens/{token}": {
"/api/v1/tokens/{tokenId}": {
"parameters": [
{
"schema": {
"type": "string"
},
"name": "token",
"name": "tokenId",
"in": "path",
"required": true,
"description": "API Token"
"description": "API Token ID"
}
],
"delete": {
@ -16429,7 +16429,7 @@
}
]
},
"/api/v1/db/meta/projects/{baseId}/api-tokens/{token}": {
"/api/v1/db/meta/projects/{baseId}/api-tokens/{tokenId}": {
"delete": {
"summary": "Delete API Token",
"operationId": "api-token-delete",
@ -16479,12 +16479,12 @@
{
"schema": {
"type": "string",
"example": "DYh540o8hbWpUGdarekECKLdN5OhlgCUWutVJYX2"
"example": "DYh540o8hbWpU"
},
"name": "token",
"name": "tokenId",
"in": "path",
"required": true,
"description": "API Token"
"description": "API Token ID"
}
]
},

8
packages/nocodb/src/services/api-tokens.service.ts

@ -37,8 +37,8 @@ export class ApiTokensService {
});
}
async apiTokenDelete(param: { token; user: User; req: NcRequest }) {
const apiToken = await ApiToken.getByToken(context, param.token);
async apiTokenDelete(param: { tokenId: string; user: User; req: NcRequest }) {
const apiToken = await ApiToken.get(param.tokenId);
if (
!extractRolesObj(param.user.roles)[OrgUserRoles.SUPER_ADMIN] &&
apiToken.fk_user_id !== param.user.id
@ -48,11 +48,11 @@ export class ApiTokensService {
this.appHooksService.emit(AppEvents.API_TOKEN_DELETE, {
userId: param.user?.id,
token: param.token,
tokenId: param.tokenId,
req: param.req,
});
// todo: verify token belongs to the user
return await ApiToken.delete(context, param.token);
return await ApiToken.delete(param.tokenId);
}
}

2
packages/nocodb/src/services/app-hooks/interfaces.ts

@ -176,7 +176,7 @@ export interface ApiTokenCreateEvent extends NcBaseEvent {
export interface ApiTokenDeleteEvent extends NcBaseEvent {
userId: string;
token: string;
tokenId: string;
}
export interface PluginTestEvent extends NcBaseEvent {

8
packages/nocodb/src/services/org-tokens.service.ts

@ -61,19 +61,19 @@ export class OrgTokensService {
return apiToken;
}
async apiTokenDelete(param: { user: User; token: string; req: NcRequest }) {
async apiTokenDelete(param: { user: User; tokenId: string; req: NcRequest }) {
const fk_user_id = param.user.id;
const apiToken = await ApiToken.getByToken(param.token);
const apiToken = await ApiToken.get(param.tokenId);
if (
!extractRolesObj(param.user.roles)[OrgUserRoles.SUPER_ADMIN] &&
apiToken.fk_user_id !== fk_user_id
) {
NcError.notFound('Token not found');
}
const res = await ApiToken.delete(param.token);
const res = await ApiToken.delete(param.tokenId);
this.appHooksService.emit(AppEvents.ORG_API_TOKEN_DELETE, {
token: param.token,
tokenId: param.tokenId,
userId: param.user?.id,
req: param['req'],
});

Loading…
Cancel
Save