Browse Source

Merge branch 'develop' into refactor/product-analytics

pull/1795/head
Raju Udava 2 years ago committed by GitHub
parent
commit
299907fa16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      .all-contributorsrc
  2. 7
      .github/workflows/sync-to-develop.yml
  3. 1
      README.md
  4. 7
      packages/nc-gui/assets/style/style.css
  5. 11
      packages/nc-gui/components/auth/shareOrInviteModal.vue
  6. 34
      packages/nc-gui/components/auth/userManagement.vue
  7. 2
      packages/nc-gui/components/importantAnnouncement.vue
  8. 2
      packages/nc-gui/components/project/appStore/inputs/checkboxField.vue
  9. 1
      packages/nc-gui/components/project/auditTab/db.vue
  10. 6
      packages/nc-gui/components/project/spreadsheet/components/columnFilter.vue
  11. 1
      packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue
  12. 2
      packages/nc-gui/components/project/spreadsheet/components/editVirtualColumn.vue
  13. 7
      packages/nc-gui/components/project/spreadsheet/components/editableCell.vue
  14. 4
      packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue
  15. 2
      packages/nc-gui/components/project/spreadsheet/components/sortListMenu.vue
  16. 28
      packages/nc-gui/components/project/spreadsheet/helpers/imageExt.js
  17. 2
      packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js
  18. 10
      packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue
  19. 4
      packages/nc-gui/components/project/spreadsheet/views/formView.vue
  20. 1
      packages/nc-gui/components/project/tableTabs/aclTsFileDbChild.vue
  21. 17
      packages/nc-gui/components/templates/help.vue
  22. 1
      packages/nc-gui/components/trialExpired.vue
  23. 41
      packages/nc-gui/helpers/index.js
  24. 2
      packages/nc-gui/lang/da.json
  25. 2
      packages/nc-gui/lang/de.json
  26. 2
      packages/nc-gui/lang/en.json
  27. 2
      packages/nc-gui/lang/es.json
  28. 2
      packages/nc-gui/lang/fi.json
  29. 2
      packages/nc-gui/lang/fr.json
  30. 2
      packages/nc-gui/lang/id.json
  31. 2
      packages/nc-gui/lang/it_IT.json
  32. 2
      packages/nc-gui/lang/iw.json
  33. 2
      packages/nc-gui/lang/ko.json
  34. 2
      packages/nc-gui/lang/no.json
  35. 2
      packages/nc-gui/lang/pt.json
  36. 2
      packages/nc-gui/lang/pt_BR.json
  37. 2
      packages/nc-gui/lang/sv.json
  38. 2
      packages/nc-gui/lang/th.json
  39. 2
      packages/nc-gui/lang/uk.json
  40. 2
      packages/nc-gui/lang/vi.json
  41. 27
      packages/nc-gui/layouts/default.vue
  42. 3
      packages/nc-gui/layouts/public.vue
  43. 6
      packages/nc-gui/package-lock.json
  44. 2
      packages/nc-gui/package.json
  45. 2
      packages/nc-gui/pages/projects/index.vue
  46. 74
      packages/nc-gui/plugins/i18n.js
  47. 4
      packages/nc-gui/store/app.js
  48. 1
      packages/nc-gui/xc.js
  49. 2
      packages/nc-lib-gui/package.json
  50. 1
      packages/noco-docs/content/en/developer-resources/rest-apis.md
  51. 2
      packages/nocodb-sdk/package-lock.json
  52. 2
      packages/nocodb-sdk/package.json
  53. 23
      packages/nocodb-sdk/src/lib/Api.ts
  54. 14
      packages/nocodb/package-lock.json
  55. 6
      packages/nocodb/package.json
  56. 76
      packages/nocodb/src/lib/noco/meta/api/projectUserApis.ts
  57. 2
      packages/nocodb/src/lib/noco/meta/helpers/NcPluginMgrv2.ts
  58. 3
      packages/nocodb/src/lib/utils/projectAcl.ts
  59. 47
      scripts/sdk/swagger.json

9
.all-contributorsrc

@ -729,6 +729,15 @@
"contributions": [
"code"
]
},
{
"login": "iamnamananand996",
"name": "Naman Anand",
"avatar_url": "https://avatars.githubusercontent.com/u/31537362?v=4",
"profile": "https://github.com/iamnamananand996",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 7,

7
.github/workflows/sync-to-develop.yml

@ -9,16 +9,11 @@ jobs:
sync-to-develop:
runs-on: ubuntu-latest
steps:
# See https://github.com/actions/checkout/issues/766
- name: Workaround for unsafe repository issue
run: |
git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: Checkout
uses: actions/checkout@v1
- name: Merge from master to develop
uses: robotology/gh-action-nightly-merge@v1.3.1
uses: wingkwong/gh-action-nightly-merge@master
with:
stable_branch: 'master'
development_branch: 'develop'

1
README.md

@ -442,6 +442,7 @@ Our mission is to provide the most powerful no-code interface for databases whic
<td align="center"><a href="https://github.com/RobinFrcd"><img src="https://avatars.githubusercontent.com/u/29704178?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Robin Fourcade</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=RobinFrcd" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/zprial"><img src="https://avatars.githubusercontent.com/u/33095380?v=4?s=100" width="100px;" alt=""/><br /><sub><b>zprial</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=zprial" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/nilsreichardt"><img src="https://avatars.githubusercontent.com/u/24459435?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nils Reichardt</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=nilsreichardt" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/iamnamananand996"><img src="https://avatars.githubusercontent.com/u/31537362?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Naman Anand</b></sub></a><br /><a href="https://github.com/nocodb/nocodb/commits?author=iamnamananand996" title="Code">💻</a></td>
</tr>
</table>

7
packages/nc-gui/assets/style/style.css

@ -362,3 +362,10 @@ html {
.cursor-pointer{
cursor: pointer;
}
/* sorting and filter */
.menu-filter-dropdown {
max-height: 500px;
overflow-y: auto;
}

11
packages/nc-gui/components/auth/shareOrInviteModal.vue

@ -43,15 +43,8 @@
</v-alert>
<p class="caption grey--text mt-3">
{{ $t("msg.info.userInviteNoSMTP") }}
<!-- Looks like you have not configured mailer yet! <br>Please copy above -->
<!-- invite -->
<!-- link and send it to -->
{{
invite_token &&
(invite_token.email ||
(invite_token.emails && invite_token.emails.join(", ")))
}}.
<!-- Looks like you have not configured mailer yet! <br> Please copy above invite link and send it to -->
<pre>{{ $t('msg.info.userInviteNoSMTP') }} {{ invite_token && (invite_token.email || invite_token.emails && invite_token.emails.join(', ')) }}.</pre>
</p>
<div class="text-right">

34
packages/nc-gui/components/auth/userManagement.vue

@ -314,15 +314,10 @@
</v-alert>
<p class="caption grey--text mt-3">
{{ $t("msg.info.userInviteNoSMTP") }}
<!-- Looks like you have not configured mailer yet! <br>Please copy above -->
<!-- invite -->
<!-- link and send it to -->
{{
invite_token &&
(invite_token.email ||
(invite_token.emails && invite_token.emails.join(", ")))
}}.
<!-- Looks like you have not configured mailer yet! <br> Please copy above invite link and send it to -->
<pre>{{ $t('msg.info.userInviteNoSMTP') }} {{ invite_token && (invite_token.email || invite_token.emails && invite_token.emails.join(', ')) }}.</pre>
</p>
<div class="text-right">
@ -646,22 +641,11 @@ export default {
},
async resendInvite(id) {
try {
await this.$axios.post(
"/admin/resendInvite/" + id,
{
projectName: this.$store.getters["project/GtrProjectName"],
},
{
headers: {
"xc-auth": this.$store.state.users.token,
},
params: {
project_id: this.$route.params.project_id,
},
}
);
this.$toast.success("Invite email sent successfully").goAway(3000);
await this.loadUsers();
await this.$api.auth.projectUserResendInvite(this.$route.params.project_id, id)
this.$toast.success('Invite email sent successfully').goAway(3000)
await this.loadUsers()
} catch (e) {
this.$toast.error(e.response.data.msg).goAway(3000);
}

2
packages/nc-gui/components/importantAnnouncement.vue

@ -67,7 +67,7 @@ export default {
set(val) {
return this.$store.commit('app/MutHiddenAnnouncement', val ? null : true)
}
},
}
},
mounted() {
setTimeout(() => {

2
packages/nc-gui/components/project/appStore/inputs/checkboxField.vue

@ -28,7 +28,7 @@ export default {
const $listeners = {}
return $listeners
}
},
}
}
</script>

1
packages/nc-gui/components/project/auditTab/db.vue

@ -407,7 +407,6 @@ export default {
},
async migrationUp(steps = 99999999999) {
try {
await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'migrationsUp', {
env: this.nodes.env,
dbAlias: this.nodes.dbAlias,

6
packages/nc-gui/components/project/spreadsheet/components/columnFilter.vue

@ -1,7 +1,9 @@
<template>
<div
class="backgroundColor pa-2"
:style="{ width: nested ? '100%' : '530px' }"
class="backgroundColor pa-2 menu-filter-dropdown"
:style="{width:nested ? '100%' : '530px'}"
>
<div class="grid" @click.stop>
<template v-for="(filter, i) in filters" dense>

1
packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue

@ -78,7 +78,6 @@ export default {
}))
return refTables
},
columnList() {
return ((

2
packages/nc-gui/components/project/spreadsheet/components/editVirtualColumn.vue

@ -6,7 +6,7 @@
style="overflow: auto"
class=" card nc-col-create-or-edit-card"
>
<v-form v-model="valid">
<v-form v-model="valid" @submit.prevent="save">
<v-container fluid @click.stop.prevent>
<v-row>
<v-col cols="12">

7
packages/nc-gui/components/project/spreadsheet/components/editableCell.vue

@ -184,10 +184,8 @@ export default {
this.$emit('input', val)
if (this.isAttachment || this.isEnum || this.isBoolean || this.isSet || this.isTime || this.isDateTime || this.isDate) {
this.syncData()
} else {
if (!this.isCurrency) {
this.syncDataDebounce(this)
}
} else if (!this.isCurrency) {
this.syncDataDebounce(this)
}
}
}
@ -206,7 +204,6 @@ export default {
$listeners.cancel = this.$listeners.cancel
}
return $listeners
}

4
packages/nc-gui/components/project/spreadsheet/components/importExport/columnMappingModal.vue

@ -154,8 +154,8 @@ export default {
// check if the input contains null value for a required column
if (v.pk ? !v.ai && !v.cdf : !v.cdf && v.rqd) {
if (this.parsedCsv && this.parsedCsv.data && this.parsedCsv.data.slice(0, 500)
.some(r => r[row.sourceCn] === null || r[row.sourceCn] === undefined || r[row.sourceCn] === "" )) {
return `null value violates not-null constraint`
.some(r => r[row.sourceCn] === null || r[row.sourceCn] === undefined || r[row.sourceCn] === '')) {
return 'null value violates not-null constraint'
}
}

2
packages/nc-gui/components/project/spreadsheet/components/sortListMenu.vue

@ -22,7 +22,7 @@
</v-btn>
</v-badge>
</template>
<div class="backgroundColor pa-2" style="min-width: 330px">
<div class="backgroundColor pa-2 menu-filter-dropdown" style="min-width: 330px">
<div class="sort-grid" @click.stop>
<template v-for="(sort, i) in sortList || []" dense>
<v-icon

28
packages/nc-gui/components/project/spreadsheet/helpers/imageExt.js

@ -1,22 +1,22 @@
const imageExt = [
"jpeg",
"gif",
"png",
"png",
"svg",
"bmp",
"ico",
"jpg",
"webp",
];
'jpeg',
'gif',
'png',
'png',
'svg',
'bmp',
'ico',
'jpg',
'webp'
]
export default imageExt;
export default imageExt
const isImage = (name) => {
return imageExt.some((e) => name.toLowerCase().endsWith(`.${e}`));
};
return imageExt.some(e => name.toLowerCase().endsWith(`.${e}`))
}
export { isImage };
export { isImage }
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*

2
packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js

@ -145,7 +145,7 @@ export default {
concatenatedXWhere() {
let where = ''
if (this.searchField && this.searchQuery.trim()) {
const col = this.availableColumns.find(({ _cn }) => _cn === this.searchField) || this.availableColumns[0]
const col = this.availableColumns.find(({ alias }) => alias === this.searchField) || this.availableColumns[0]
// bigint values are displayed in string format in UI
// when searching bigint values, the operator should be 'eq' instead of 'like'
if (['text', 'string'].includes(this.sqlUi.getAbstractType(col)) && col.dt !== 'bigint') {

10
packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue

@ -597,13 +597,9 @@
</span>
</v-list-item>
</template>
<template
v-if="
rowContextMenu.col &&
!rowContextMenu.col.rqd &&
!rowContextMenu.col.virtual
"
>
<template v-if="isEditable && !isLocked && rowContextMenu.col && !rowContextMenu.col.rqd && !rowContextMenu.col.virtual">
<v-tooltip bottom>
<template #activator="{ on }">
<v-list-item

4
packages/nc-gui/components/project/spreadsheet/views/formView.vue

@ -689,9 +689,7 @@ export default {
},
columns: {
get() {
return this.fields
.filter((f) => f.show)
.sort((a, b) => a.order - b.order);
return this.fields.filter(f => f.show && f.uidt != UITypes.Rollup && f.uidt != UITypes.Lookup).sort((a, b) => a.order - b.order)
},
set(v) {},
},

1
packages/nc-gui/components/project/tableTabs/aclTsFileDbChild.vue

@ -341,7 +341,6 @@ export default {
},
async save() {
try {
await this.$store.dispatch('sqlMgr/ActSqlOp', [null, 'xcRoutesPolicyUpdate', {
env: this.nodes.env,
dbAlias: this.nodes.dbAlias,

17
packages/nc-gui/components/templates/help.vue

@ -39,38 +39,39 @@ export default {
description: 'Add tables',
mac: '<kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>T</kbd>',
windows: '<kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>T</kbd>'
},{
}, {
description: 'Add columns',
mac: '<kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>C</kbd>',
windows: '<kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>C</kbd>'
},{
}, {
description: 'Add new column row',
mac: '<kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>A</kbd>',
windows: '<kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>A</kbd>'
},{
}, {
description: 'Table navigation',
mac: '<kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>Arrow Down</kbd> <br>AND<br> <kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>Arrow Up</kbd>',
windows: '<kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>Arrow Down</kbd> <br>AND<br> <kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>Arrow Up</kbd>'
},{
}, {
description: 'Column navigation',
mac: '<kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>Arrow Right</kbd> <br>AND<br> <kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>Arrow Left</kbd>',
windows: '<kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>Arrow Right</kbd> <br>AND<br> <kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>Arrow Right</kbd>'
},{
}, {
description: 'Copy json to clipboard',
mac: '<kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>J</kbd>',
windows: '<kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>J</kbd>'
},{
}, {
description: 'Submit template',
mac: '<kbd>Command</kbd> + <kbd>Control</kbd> + <kbd>S</kbd>',
windows: '<kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>S</kbd>'
},]
}]
}
},
computed: {
localState: {
get() {
return this.value
}, set(val) {
},
set(val) {
this.$emit('input', val)
}
}

1
packages/nc-gui/components/trialExpired.vue

@ -14,7 +14,6 @@
<script>
export default {
name: 'TrialExpired',
methods: {

41
packages/nc-gui/helpers/index.js

@ -75,7 +75,7 @@ function GetCaretPosition(ctrl) {
export function validateTableName(v, isGQL) {
if (!v) {
return "Table name required";
return 'Table name required'
}
// GraphQL naming convention
@ -83,67 +83,66 @@ export function validateTableName(v, isGQL) {
if (isGQL) {
if (/^[_A-Za-z][_0-9A-Za-z]*$/.test(v)) {
return true;
return true
}
if (/^[^_A-Za-z]/.test(v)) {
return "Name should start with an alphabet or _";
return 'Name should start with an alphabet or _'
}
const m = v.match(/[^_A-Za-z\d]/g);
const m = v.match(/[^_A-Za-z\d]/g)
if (m) {
return `Following characters are not allowed ${m
.map((c) => JSON.stringify(c))
.join(", ")}`;
.map(c => JSON.stringify(c))
.join(', ')}`
}
} else {
// exclude . / \
// rest all characters allowed
// https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/acreldb/n0rfg6x1shw0ppn1cwhco6yn09f7.htm#:~:text=By%20default%2C%20MySQL%20encloses%20column,not%20truncate%20a%20longer%20name.
const m = v.match(/[./\\]/g);
const m = v.match(/[./\\]/g)
if (m) {
return `Following characters are not allowed ${m
.map((c) => JSON.stringify(c))
.join(", ")}`;
.map(c => JSON.stringify(c))
.join(', ')}`
}
return true;
return true
}
}
export function validateColumnName(v, isGQL) {
if (!v) {
return "Column name required";
return 'Column name required'
}
// GraphQL naming convention
// http://spec.graphql.org/June2018/#Name
if (isGQL) {
if (/^[_A-Za-z][_0-9A-Za-z]*$/.test(v)) {
return true;
return true
}
if (/^[^_A-Za-z]/.test(v)) {
return "Name should start with an alphabet or _";
return 'Name should start with an alphabet or _'
}
const m = v.match(/[^_A-Za-z\d]/g);
const m = v.match(/[^_A-Za-z\d]/g)
if (m) {
return `Following characters are not allowed ${m
.map((c) => JSON.stringify(c))
.join(", ")}`;
.map(c => JSON.stringify(c))
.join(', ')}`
}
} else {
// exclude . / \
// rest all characters allowed
// https://documentation.sas.com/doc/en/pgmsascdc/9.4_3.5/acreldb/n0rfg6x1shw0ppn1cwhco6yn09f7.htm#:~:text=By%20default%2C%20MySQL%20encloses%20column,not%20truncate%20a%20longer%20name.
const m = v.match(/[./\\]/g);
const m = v.match(/[./\\]/g)
if (m) {
return `Following characters are not allowed ${m
.map((c) => JSON.stringify(c))
.join(", ")}`;
.map(c => JSON.stringify(c))
.join(', ')}`
}
return true;
return true
}
}

2
packages/nc-gui/lang/da.json

@ -406,7 +406,7 @@
"deleteProject": "Ønsker du at slette projektet?",
"shareBasePrivate": "Generer offentligt delbart readonly base",
"shareBasePublic": "Enhver på internettet med dette link kan se",
"userInviteNoSMTP": "Ser ud som om du ikke har konfigureret mailer endnu! \\ n Kopier venligst ovenstående invitation link og send det til",
"userInviteNoSMTP": "Ser ud som om du ikke har konfigureret mailer endnu!\nKopier venligst ovenstående invitation link og send det til",
"dragDropHide": "Træk og slip felter her for at skjule",
"formInput": "Indtast formularindgangsmærke",
"formHelpText": "Tilføj nogle hjælpetekst",

2
packages/nc-gui/lang/de.json

@ -406,7 +406,7 @@
"deleteProject": "Möchten Sie das Projekt löschen?",
"shareBasePrivate": "Öffentlich freigegebene Nur-Lese-Datenbank generieren",
"shareBasePublic": "Für Jeden im Internet mit diesem Link sichtbar",
"userInviteNoSMTP": "Es sieht so aus, als hätten Sie den Mailer noch nicht konfiguriert! \\ n Bitte kopieren Sie den obigen Einladungs-Link und senden Sie ihn an",
"userInviteNoSMTP": "Es sieht so aus, als hätten Sie den Mailer noch nicht konfiguriert!\nBitte kopieren Sie den obigen Einladungs-Link und senden Sie ihn an",
"dragDropHide": "Ziehen Sie die Felder hierher, um sie zu verstecken",
"formInput": "Formularbezeichnung eingeben",
"formHelpText": "Einen Hilfs-Text hinzufügen",

2
packages/nc-gui/lang/en.json

@ -406,7 +406,7 @@
"deleteProject": "Do you want to delete the project?",
"shareBasePrivate": "Generate publicly shareable readonly base",
"shareBasePublic": "Anyone on the internet with this link can view",
"userInviteNoSMTP": "Looks like you have not configured mailer yet! \\n Please copy above invite link and send it to",
"userInviteNoSMTP": "Looks like you have not configured mailer yet!\nPlease copy above invite link and send it to",
"dragDropHide": "Drag and drop fields here to hide",
"formInput": "Enter form input label",
"formHelpText": "Add some help text",

2
packages/nc-gui/lang/es.json

@ -406,7 +406,7 @@
"deleteProject": "¿Quieres eliminar el proyecto?",
"shareBasePrivate": "Generar una base de sólo lectura compartible públicamente",
"shareBasePublic": "Cualquier persona en Internet con este enlace puede ver",
"userInviteNoSMTP": "¡Parece que aún no has configurado Mailer! \\ n Por favor, copia el link de invitación de arriba y envíalo a",
"userInviteNoSMTP": "¡Parece que aún no has configurado Mailer!\nPor favor, copia el link de invitación de arriba y envíalo a",
"dragDropHide": "Arrastra y suelta los campos a ocultar aquí",
"formInput": "Ingrese la etiqueta de entrada del formulario",
"formHelpText": "Añade algo de texto de ayuda",

2
packages/nc-gui/lang/fi.json

@ -406,7 +406,7 @@
"deleteProject": "Haluatko poistaa projektin?",
"shareBasePrivate": "Luo julkisesti jakattava Readonly Base",
"shareBasePublic": "Jokainen Internetissä tällä linkillä voi tarkastella",
"userInviteNoSMTP": "Näyttää siltä, ettet ole määrittänyt sähköpostia! \\ n Kopioi yllä kutsun linkki ja lähetä se",
"userInviteNoSMTP": "Näyttää siltä, ettet ole määrittänyt sähköpostia!\nKopioi yllä kutsun linkki ja lähetä se",
"dragDropHide": "Vedä ja pudota kentät täällä piiloutumaan",
"formInput": "Anna lomakkeen syöttömerkki",
"formHelpText": "Lisää joitain ohjeita",

2
packages/nc-gui/lang/fr.json

@ -406,7 +406,7 @@
"deleteProject": "Voulez-vous supprimer le projet ?",
"shareBasePrivate": "Générer une base partagée en lecture seule",
"shareBasePublic": "Toute personne avec ce lien peut consulter",
"userInviteNoSMTP": "On dirait que vous n'avez pas encore configuré Mailer! \\ n Merci de copier-coller le lien d'invitation ci-dessous et l'envoyer à",
"userInviteNoSMTP": "On dirait que vous n'avez pas encore configuré Mailer!\nMerci de copier-coller le lien d'invitation ci-dessous et l'envoyer à",
"dragDropHide": "Glisser et déposer des champs ici pour masquer",
"formInput": "Entrer le libelé du formulaire",
"formHelpText": "Ajouter du texte d'assitance",

2
packages/nc-gui/lang/id.json

@ -406,7 +406,7 @@
"deleteProject": "Apakah Anda ingin menghapus proyek?",
"shareBasePrivate": "Menghasilkan basis readonly yang dapat dibagikan secara publik",
"shareBasePublic": "Siapa pun di Internet dengan tautan ini dapat dilihat",
"userInviteNoSMTP": "Sepertinya Anda belum mengonfigurasi mailer! \\ n Harap salin tautan undangan di atas dan kirimkan ke",
"userInviteNoSMTP": "Sepertinya Anda belum mengonfigurasi mailer!\nHarap salin tautan undangan di atas dan kirimkan ke",
"dragDropHide": "Seret dan jatuhkan bidang di sini untuk bersembunyi",
"formInput": "Masukkan label input formulir",
"formHelpText": "Tambahkan beberapa teks bantuan",

2
packages/nc-gui/lang/it_IT.json

@ -406,7 +406,7 @@
"deleteProject": "Vuoi cancellare il progetto?",
"shareBasePrivate": "Genera base readonly condivisibile pubblicamente condivisa",
"shareBasePublic": "Chiunque su Internet con questo link può visualizzare",
"userInviteNoSMTP": "Sembra che non abbia ancora configurato mailer! \\ n Si prega di copiare sopra Invita link e invialo a",
"userInviteNoSMTP": "Sembra che non abbia ancora configurato mailer!\nSi prega di copiare sopra Invita link e invialo a",
"dragDropHide": "Trascina e rilascia i campi qui per nascondersi",
"formInput": "Inserisci l'etichetta di input del modulo",
"formHelpText": "Aggiungi un po 'di testo di aiuto",

2
packages/nc-gui/lang/iw.json

@ -406,7 +406,7 @@
"deleteProject": "האם ברצונך למחוק את הפרויקט?",
"shareBasePrivate": "ליצור בסיס שיתוף פעולה לציבור",
"shareBasePublic": "כל אחד באינטרנט עם קישור זה יכול להציג",
"userInviteNoSMTP": "נראה כאילו לא הגדרת מיילר עדיין! \\ N אנא העתק מעל הזמנת קישור ולשלוח אותו",
"userInviteNoSMTP": "נראה כאילו לא הגדרת מיילר עדיין!\nאנא העתק מעל הזמנת קישור ולשלוח אותו",
"dragDropHide": "גרור ושחרר שדות כאן כדי להסתיר",
"formInput": "הזן תווית קלט טופס",
"formHelpText": "הוסף טקסט עזרה",

2
packages/nc-gui/lang/ko.json

@ -406,7 +406,7 @@
"deleteProject": "프로젝트를 삭제 하시겠습니까?",
"shareBasePrivate": "공개적으로 공유 할 수있는 ReadOnly Base를 생성합니다",
"shareBasePublic": "이 링크가있는 인터넷의 모든 사람은 볼 수 있습니다",
"userInviteNoSMTP": "아직 메일러를 구성하지 않은 것처럼 보입니다! \\ n 초대장 링크를 복사하여 보냅니다.",
"userInviteNoSMTP": "아직 메일러를 구성하지 않은 것처럼 보입니다!\n초대장 링크를 복사하여 보냅니다.",
"dragDropHide": "여기에서 필드를 드래그 앤 드롭하십시오",
"formInput": "양식 입력 레이블을 입력하십시오",
"formHelpText": "도움말 텍스트를 추가하십시오",

2
packages/nc-gui/lang/no.json

@ -406,7 +406,7 @@
"deleteProject": "Ønsker du å slette prosjektet?",
"shareBasePrivate": "Generer offentlig delbar readonly base",
"shareBasePublic": "Alle på Internett med denne lenken kan se",
"userInviteNoSMTP": "Ser ut som om du ikke har konfigurert mailer ennå! \\ n Vennligst kopier over Inviter Link og send den til",
"userInviteNoSMTP": "Ser ut som om du ikke har konfigurert mailer ennå!\nVennligst kopier over Inviter Link og send den til",
"dragDropHide": "Dra og slipp felt her for å skjule",
"formInput": "Skriv inn skjema inngangsetikett",
"formHelpText": "Legg til litt hjelpetekst",

2
packages/nc-gui/lang/pt.json

@ -406,7 +406,7 @@
"deleteProject": "Você quer excluir o projeto?",
"shareBasePrivate": "Gerar base readonly compartilhável publicamente",
"shareBasePublic": "Qualquer pessoa na internet com este link pode ver",
"userInviteNoSMTP": "Parece que você ainda não configurou o mailer! \\ n por favor copie o link acima do convite e envie-o para",
"userInviteNoSMTP": "Parece que você ainda não configurou o mailer!\npor favor copie o link acima do convite e envie-o para",
"dragDropHide": "Arraste e solte os campos aqui para se esconder",
"formInput": "Digite a etiqueta de entrada do formulário",
"formHelpText": "Adicione um texto de ajuda",

2
packages/nc-gui/lang/pt_BR.json

@ -406,7 +406,7 @@
"deleteProject": "Você quer excluir o projeto?",
"shareBasePrivate": "Gerar base readonly compartilhável publicamente",
"shareBasePublic": "Qualquer pessoa na internet com este link pode ver",
"userInviteNoSMTP": "Parece que você ainda não configurou o mailer! \\ n por favor copie o link acima do convite e envie-o para",
"userInviteNoSMTP": "Parece que você ainda não configurou o mailer!\npor favor copie o link acima do convite e envie-o para",
"dragDropHide": "Arraste e solte os campos aqui para se esconder",
"formInput": "Digite a etiqueta de entrada do formulário",
"formHelpText": "Adicione um texto de ajuda",

2
packages/nc-gui/lang/sv.json

@ -406,7 +406,7 @@
"deleteProject": "Vill du radera projektet?",
"shareBasePrivate": "Generera offentligt delbar readonly base",
"shareBasePublic": "Någon på internet med den här länken kan visa",
"userInviteNoSMTP": "Det verkar som om du inte har konfigurerat Mailer än! \\ n Vänligen kopiera ovanför bjudningslänk och skicka den till",
"userInviteNoSMTP": "Det verkar som om du inte har konfigurerat Mailer än!\nVänligen kopiera ovanför bjudningslänk och skicka den till",
"dragDropHide": "Dra och släpp fält här för att dölja",
"formInput": "Ange formulärinmatningslabel",
"formHelpText": "Lägg till lite hjälptext",

2
packages/nc-gui/lang/th.json

@ -406,7 +406,7 @@
"deleteProject": "คณตองการลบโครงการหรอไม",
"shareBasePrivate": "สรางฐาน Readonly ทใชวมกนไดอยางเปดเผย",
"shareBasePublic": "ทกคนบนอนเทอรเนตดวยลงคสามารถดได",
"userInviteNoSMTP": "ดเหมอนวาคณยงไมไดกำหนดคาเมล! \\ n โปรดคดลอกลงกเชญดานบนและสงไปท",
"userInviteNoSMTP": "ดเหมอนวาคณยงไมไดกำหนดคาเมล!\nโปรดคดลอกลงกเชญดานบนและสงไปท",
"dragDropHide": "ลากและวางฟลดเพอซอน",
"formInput": "ปอนปายชออนพตแบบฟอรม",
"formHelpText": "เพมขอความชวยเหลอบางอยาง",

2
packages/nc-gui/lang/uk.json

@ -406,7 +406,7 @@
"deleteProject": "Ви хочете видалити проект?",
"shareBasePrivate": "Генерувати загальнодоступну групою",
"shareBasePublic": "Будь-хто в Інтернеті за допомогою цього посилання може переглядати",
"userInviteNoSMTP": "Схоже, ви ще не налаштували Mailer! \\ n Будь ласка, скопіюйте вище посилання на запрошення і надішліть його",
"userInviteNoSMTP": "Схоже, ви ще не налаштували Mailer!\nБудь ласка, скопіюйте вище посилання на запрошення і надішліть його",
"dragDropHide": "Перетягніть поля тут, щоб приховати",
"formInput": "Введіть етикетку введення форми",
"formHelpText": "Додайте деякий текст довідки",

2
packages/nc-gui/lang/vi.json

@ -406,7 +406,7 @@
"deleteProject": "Bạn có muốn xóa dự án?",
"shareBasePrivate": "Tạo cơ sở chỉ đọc chia sẻ công khai",
"shareBasePublic": "Bất cứ ai trên Internet với liên kết này có thể xem",
"userInviteNoSMTP": "Có vẻ như bạn chưa định cấu hình Mailer! \\ n Vui lòng sao chép liên kết mời trên và gửi nó đến",
"userInviteNoSMTP": "Có vẻ như bạn chưa định cấu hình Mailer!\nVui lòng sao chép liên kết mời trên và gửi nó đến",
"dragDropHide": "Kéo và thả các trường ở đây để ẩn",
"formInput": "Nhập nhãn đầu vào Mẫu",
"formHelpText": "Thêm một số văn bản trợ giúp",

27
packages/nc-gui/layouts/default.vue

@ -302,19 +302,20 @@
</template>
<script>
import { mapGetters, mapActions, mapMutations } from "vuex";
import ReleaseInfo from "@/components/releaseInfo";
import "splitpanes/dist/splitpanes.css";
import XBtn from "../components/global/xBtn";
import dlgUnexpectedError from "../components/utils/dlgUnexpectedError";
import settings from "../components/settings";
import { copyTextToClipboard } from "@/helpers/xutils";
import Snackbar from "~/components/snackbar";
import Language from "~/components/utils/language";
import Loader from "~/components/loader";
import PreviewAs from "~/components/previewAs";
import ShareOrInviteModal from "~/components/auth/shareOrInviteModal";
import ImportantAnnouncement from "../components/importantAnnouncement.vue";
import { mapGetters, mapActions, mapMutations } from 'vuex'
import ReleaseInfo from '@/components/releaseInfo'
import 'splitpanes/dist/splitpanes.css'
import XBtn from '../components/global/xBtn'
import dlgUnexpectedError from '../components/utils/dlgUnexpectedError'
import settings from '../components/settings'
import { copyTextToClipboard } from '@/helpers/xutils'
import Snackbar from '~/components/snackbar'
import Language from '~/components/utils/language'
import Loader from '~/components/loader'
import PreviewAs from '~/components/previewAs'
import ShareOrInviteModal from '~/components/auth/shareOrInviteModal'
import ImportantAnnouncement from '../components/importantAnnouncement.vue'
export default {
components: {

3
packages/nc-gui/layouts/public.vue

@ -14,7 +14,8 @@
<template #activator="{ on }">
<v-btn
to="/projects"
icon class="pa-1 brand-icon nc-noco-brand-icon"
icon
class="pa-1 brand-icon nc-noco-brand-icon"
v-on="on"
>
<v-img :src="require('~/assets/img/icons/512x512-trans.png')" max-height="30px" max-width="30px" />

6
packages/nc-gui/package-lock.json generated

@ -7876,9 +7876,9 @@
}
},
"nocodb-sdk": {
"version": "0.90.3",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.90.3.tgz",
"integrity": "sha512-qoQbuSIb/5qYyldZjtwZY6eZaQWzL/Z9pfsM+Aw8HivsyIqRLboKCAVEr6gJf/QToro49NEzjgisKMeX/YLB+w==",
"version": "0.90.5",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.90.5.tgz",
"integrity": "sha512-5H2nuVvt9n2DTQs9NMKtooGBXPpGjPoHIy6szXb+feigE2N8QPZNNt3YgpK9QaEG6mTpr04kXgCvFp0QsgV6Xg==",
"requires": {
"axios": "^0.21.1",
"jsep": "^0.4.0"

2
packages/nc-gui/package.json

@ -29,7 +29,7 @@
"monaco-editor": "^0.19.3",
"monaco-themes": "^0.2.5",
"nano-assign": "^1.0.1",
"nocodb-sdk": "0.90.3",
"nocodb-sdk": "0.90.5",
"nuxt": "^2.14.0",
"odometer": "^0.4.8",
"papaparse": "^5.3.1",

2
packages/nc-gui/pages/projects/index.vue

@ -790,7 +790,7 @@ export default {
this.statusUpdatingProjectId = projectId;
this.projectStatusUpdating = true;
try {
await this.$api.project.delete(projectId);
await this.$api.project.delete(projectId)
this.$toast
.success(`Project '${project.title}' deleted successfully`)
.goAway(3000);

74
packages/nc-gui/plugins/i18n.js

@ -1,10 +1,10 @@
// plugins/i18n.js
import Vue from "vue";
import VueI18n from "vue-i18n";
import Vue from 'vue'
import VueI18n from 'vue-i18n'
// Tell Vue to use our plugin
Vue.use(VueI18n);
Vue.use(VueI18n)
export default ({ app, store }) => {
// Set the i18n instance on app
@ -14,49 +14,49 @@ export default ({ app, store }) => {
locale: store.state.windows.language,
// Set the fallback locale in case the current locale can't be found
fallbackLocale: "en",
fallbackLocale: 'en',
// Associate each locale to a content file
messages: {
en: require("~/lang/en.json"),
zh_HK: require("~/lang/zh_HK.json"),
zh_TW: require("~/lang/zh_TW.json"),
zh_CN: require("~/lang/zh_CN.json"),
ja: require("~/lang/ja.json"),
fr: require("~/lang/fr.json"),
es: require("~/lang/es.json"),
de: require("~/lang/de.json"),
id: require("~/lang/id.json"),
it_IT: require("~/lang/it_IT.json"),
ko: require("~/lang/ko.json"),
lv: require("~/lang/lv.json"),
nl: require("~/lang/nl.json"),
ru: require("~/lang/ru.json"),
sv: require("~/lang/sv.json"),
da: require("~/lang/da.json"),
vi: require("~/lang/vi.json"),
no: require("~/lang/no.json"),
iw: require("~/lang/iw.json"),
fi: require("~/lang/fi.json"),
uk: require("~/lang/uk.json"),
hr: require("~/lang/hr.json"),
th: require("~/lang/th.json"),
sl: require("~/lang/sl.json"),
pt_BR: require("~/lang/pt_BR.json"),
fa: require("~/lang/fa.json"),
tr: require("~/lang/tr.json"),
},
});
en: require('~/lang/en.json'),
zh_HK: require('~/lang/zh_HK.json'),
zh_TW: require('~/lang/zh_TW.json'),
zh_CN: require('~/lang/zh_CN.json'),
ja: require('~/lang/ja.json'),
fr: require('~/lang/fr.json'),
es: require('~/lang/es.json'),
de: require('~/lang/de.json'),
id: require('~/lang/id.json'),
it_IT: require('~/lang/it_IT.json'),
ko: require('~/lang/ko.json'),
lv: require('~/lang/lv.json'),
nl: require('~/lang/nl.json'),
ru: require('~/lang/ru.json'),
sv: require('~/lang/sv.json'),
da: require('~/lang/da.json'),
vi: require('~/lang/vi.json'),
no: require('~/lang/no.json'),
iw: require('~/lang/iw.json'),
fi: require('~/lang/fi.json'),
uk: require('~/lang/uk.json'),
hr: require('~/lang/hr.json'),
th: require('~/lang/th.json'),
sl: require('~/lang/sl.json'),
pt_BR: require('~/lang/pt_BR.json'),
fa: require('~/lang/fa.json'),
tr: require('~/lang/tr.json')
}
})
store.watch(
(state) => state.windows.language,
state => state.windows.language,
(language) => {
if (app.i18n.availableLocales.includes(language)) {
app.i18n.locale = language;
app.i18n.locale = language
}
}
);
};
)
}
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*

4
packages/nc-gui/store/app.js

@ -2,7 +2,7 @@ export const state = () => ({
releaseVersion: null,
hiddenRelease: null,
latestRelease: null,
hiddenAnnouncement: null,
hiddenAnnouncement: null
})
export const mutations = {
@ -17,7 +17,7 @@ export const mutations = {
},
MutHiddenAnnouncement(state, hiddenAnnouncement) {
state.hiddenAnnouncement = hiddenAnnouncement
},
}
}
/**

1
packages/nc-gui/xc.js

@ -2,7 +2,6 @@
function initApp(config) {
const nuxtApp = document.createElement('div')
nuxtApp.id = '__nuxt'
document.querySelector(config.selector).appendChild(nuxtApp);
[

2
packages/nc-lib-gui/package.json

@ -1,6 +1,6 @@
{
"name": "nc-lib-gui",
"version": "0.90.3",
"version": "0.90.5",
"description": "> TODO: description",
"author": "“pranavxc” <pranavxc@gmail.com>",
"homepage": "https://gitlab.com/xgenecloud-ts/xgenecloud-ts#readme",

1
packages/noco-docs/content/en/developer-resources/rest-apis.md

@ -78,6 +78,7 @@ Currently, the default value for {orgs} is <b>noco</b>. Users will be able to ch
| Meta | Post | auth | projectUserAdd | /api/v1/db/meta/projects/{projectId}/users |
| Meta | Patch | auth | projectUserUpdate | /api/v1/db/meta/projects/{projectId}/users/{userId} |
| Meta | Delete| auth | projectUserRemove | /api/v1/db/meta/projects/{projectId}/users/{userId} |
| Meta | Post | auth | projectUserResendInvite | /api/v1/db/meta/projects/{projectId}/users/{userId}/resend-invite |
| Meta | Post | dbTable | create | /api/v1/db/meta/projects/{projectId}/tables |
| Meta | Get | dbTable | list | /api/v1/db/meta/projects/{projectId}/tables |
| Meta | Post | dbTableColumn | create | /api/v1/db/meta/tables/{tableId}/columns |

2
packages/nocodb-sdk/package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "nocodb-sdk",
"version": "0.90.3",
"version": "0.90.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

2
packages/nocodb-sdk/package.json

@ -1,6 +1,6 @@
{
"name": "nocodb-sdk",
"version": "0.90.3",
"version": "0.90.5",
"description": "NocoDB SDK",
"main": "build/main/index.js",
"typings": "build/main/index.d.ts",

23
packages/nocodb-sdk/src/lib/Api.ts

@ -1063,6 +1063,29 @@ export class Api<
format: 'json',
...params,
}),
/**
* @description Resend Invitation to a specific user
*
* @tags Auth
* @name ProjectUserResendInvite
* @request POST:/api/v1/db/meta/projects/{projectId}/users/{userId}/resend-invite
* @response `200` `any` OK
*/
projectUserResendInvite: (
projectId: string,
userId: string,
data: any,
params: RequestParams = {}
) =>
this.request<any, any>({
path: `/api/v1/db/meta/projects/${projectId}/users/${userId}/resend-invite`,
method: 'POST',
body: data,
type: ContentType.Json,
format: 'json',
...params,
}),
};
project = {
/**

14
packages/nocodb/package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "nocodb",
"version": "0.90.3",
"version": "0.90.5",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@ -12483,9 +12483,9 @@
}
},
"nc-lib-gui": {
"version": "0.90.3",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.90.3.tgz",
"integrity": "sha512-3ii6JGz0OV5c04GmR+61ToOnKsLR9pE08VJsmDPod7pOt15uDtL8yYrJBuqHi3NmPkEhm86FtNOT6TXFdE9dzg==",
"version": "0.90.5",
"resolved": "https://registry.npmjs.org/nc-lib-gui/-/nc-lib-gui-0.90.5.tgz",
"integrity": "sha512-P/6LXq6xcHx+hpwXeN87zPHUeQXPUut8Rje2WfpF0uMhth+pBZAT7qpeBOu7fpp8YjzZd6YZ2w3jM1DiJDhuzw==",
"requires": {
"axios": "^0.19.2",
"body-parser": "^1.19.0",
@ -12592,9 +12592,9 @@
"dev": true
},
"nocodb-sdk": {
"version": "0.90.3",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.90.3.tgz",
"integrity": "sha512-qoQbuSIb/5qYyldZjtwZY6eZaQWzL/Z9pfsM+Aw8HivsyIqRLboKCAVEr6gJf/QToro49NEzjgisKMeX/YLB+w==",
"version": "0.90.5",
"resolved": "https://registry.npmjs.org/nocodb-sdk/-/nocodb-sdk-0.90.5.tgz",
"integrity": "sha512-5H2nuVvt9n2DTQs9NMKtooGBXPpGjPoHIy6szXb+feigE2N8QPZNNt3YgpK9QaEG6mTpr04kXgCvFp0QsgV6Xg==",
"requires": {
"axios": "^0.21.1",
"jsep": "^0.4.0"

6
packages/nocodb/package.json

@ -1,6 +1,6 @@
{
"name": "nocodb",
"version": "0.90.3",
"version": "0.90.5",
"description": "NocoDB",
"main": "dist/bundle.js",
"repository": "https://github.com/nocodb/nocodb",
@ -151,10 +151,10 @@
"nanoid": "^3.1.20",
"nc-common": "0.0.6",
"nc-help": "^0.2.44",
"nc-lib-gui": "0.90.3",
"nc-lib-gui": "0.90.5",
"nc-plugin": "^0.1.1",
"ncp": "^2.0.0",
"nocodb-sdk": "0.90.3",
"nocodb-sdk": "0.90.5",
"nodemailer": "^6.4.10",
"ora": "^4.0.4",
"os-locale": "^5.0.0",

76
packages/nocodb/src/lib/noco/meta/api/projectUserApis.ts

@ -9,7 +9,11 @@ import User from '../../../noco-models/User';
import { Tele } from 'nc-help';
import Audit from '../../../noco-models/Audit';
import NocoCache from '../../../noco-cache/NocoCache';
import { CacheGetType, CacheScope } from '../../../utils/globals';
import { CacheGetType, CacheScope, MetaTable } from '../../../utils/globals';
import * as ejs from 'ejs';
import NcPluginMgrv2 from '../helpers/NcPluginMgrv2';
import Noco from '../../Noco';
import { PluginCategory } from 'nocodb-sdk';
async function userList(req, res) {
res.json({
@ -112,15 +116,12 @@ async function userInvite(req, res, next): Promise<any> {
// in case of single user check for smtp failure
// and send back token if failed
if (
emails.length === 1
// todo: email
// &&
// !(await sendInviteEmail(email, invite_token, req))
emails.length === 1 &&
!(await sendInviteEmail(email, invite_token, req))
) {
return res.json({ invite_token, email });
} else {
// todo: email
// sendInviteEmail(email, invite_token, req);
sendInviteEmail(email, invite_token, req);
}
} catch (e) {
console.log(e);
@ -209,16 +210,13 @@ async function projectUserDelete(req, res): Promise<any> {
NcError.forbidden('Insufficient privilege to delete a owner user.');
}
// await this.users.where('id', req.params.id).del();
await ProjectUser.delete(project_id, req.params.userId);
res.json({
msg: 'success'
});
}
// todo: map api
// @ts-ignore
async function resendInvite(req, res, next): Promise<any> {
async function projectUserInviteResend(req, res): Promise<any> {
const user = await User.get(req.params.userId);
if (!user) {
@ -233,8 +231,18 @@ async function resendInvite(req, res, next): Promise<any> {
invite_token_expires: new Date(Date.now() + 24 * 60 * 60 * 1000)
});
// todo:
// await sendInviteEmail(user.email, invite_token, req);
const pluginData = await Noco.ncMeta.metaGet2(null, null, MetaTable.PLUGIN, {
category: PluginCategory.EMAIL,
active: true
});
if (!pluginData) {
NcError.badRequest(
`No Email Plugin is found. Please go to App Store to configure first or copy the invitation URL to users instead.`
);
}
await sendInviteEmail(user.email, invite_token, req);
Audit.insert({
op_type: 'AUTHENTICATION',
@ -248,6 +256,44 @@ async function resendInvite(req, res, next): Promise<any> {
res.json({ msg: 'success' });
}
async function sendInviteEmail(
email: string,
token: string,
req: any
): Promise<any> {
try {
const template = (await import('./userApi/ui/emailTemplates/invite'))
.default;
const emailAdapter = await NcPluginMgrv2.emailAdapter();
if (emailAdapter) {
await emailAdapter.mailSend({
to: email,
subject: 'Verify email',
html: ejs.render(template, {
signupLink: `${req.ncSiteUrl}${
Noco.getConfig()?.dashboardPath
}#/user/authentication/signup/${token}`,
projectName: req.body?.projectName,
roles: (req.body?.roles || '')
.split(',')
.map(r => r.replace(/^./, m => m.toUpperCase()))
.join(', '),
adminEmail: req.session?.passport?.user?.email
})
});
return true;
}
} catch (e) {
console.log(
'Warning : `mailSend` failed, Please configure emailClient configuration.',
e.message
);
throw e;
}
}
const router = Router({ mergeParams: true });
router.get(
'/api/v1/db/meta/projects/:projectId/users',
@ -265,4 +311,8 @@ router.delete(
'/api/v1/db/meta/projects/:projectId/users/:userId',
ncMetaAclMw(projectUserDelete, 'projectUserDelete')
);
router.post(
'/api/v1/db/meta/projects/:projectId/users/:userId/resend-invite',
ncMetaAclMw(projectUserInviteResend, 'projectUserInviteResend')
);
export default router;

2
packages/nocodb/src/lib/noco/meta/helpers/NcPluginMgrv2.ts

@ -134,6 +134,8 @@ class NcPluginMgrv2 {
active: true
});
if (!pluginData) return null;
const pluginConfig = defaultPlugins.find(
c => c.title === pluginData.title && c.category === PluginCategory.EMAIL
);

3
packages/nocodb/src/lib/utils/projectAcl.ts

@ -127,7 +127,8 @@ export default {
bulkDataDeleteAll: true,
relationDataRemove: true,
relationDataAdd: true,
dataCount: true
dataCount: true,
upload: true
},
commenter: {
formViewGet: true,

47
scripts/sdk/swagger.json

@ -4821,6 +4821,51 @@
}
]
}
},
"/api/v1/db/meta/projects/{projectId}/users/{userId}/resend-invite": {
"parameters": [
{
"schema": {
"type": "string"
},
"name": "projectId",
"in": "path",
"required": true
},
{
"schema": {
"type": "string"
},
"name": "userId",
"in": "path",
"required": true
}
],
"post": {
"summary": "",
"operationId": "auth-project-user-resend-invite",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {}
}
}
}
},
"tags": [
"Auth"
],
"description": "Resend Invitation to a specific user",
"requestBody": {
"content": {
"application/json": {
"schema": {}
}
}
}
}
}
},
"components": {
@ -7718,4 +7763,4 @@
}
}
}
}
}
Loading…
Cancel
Save