Browse Source

Merge pull request #5206 from nocodb/fix/5205-shared-form-column-edit

fix: Remove double click column edit option from shared form
pull/5221/head
Raju Udava 2 years ago committed by GitHub
parent
commit
b2a7c04e77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      packages/nc-gui/components/account/ResetPassword.vue
  2. 4
      packages/nc-gui/components/general/MiniSidebar.vue
  3. 18
      packages/nc-gui/components/smartsheet/header/Cell.vue
  4. 2
      packages/nc-gui/composables/useApi/interceptors.ts
  5. 12
      packages/nc-gui/composables/useGlobal/actions.ts
  6. 4
      packages/nc-gui/layouts/base.vue
  7. 4
      packages/nc-gui/pages/[projectType]/[projectId]/index.vue
  8. 2
      packages/nc-gui/pages/index/index/user.vue
  9. 25
      packages/nocodb-sdk/src/lib/Api.ts
  10. 34
      packages/nocodb/src/lib/meta/api/userApi/userApis.ts
  11. 28
      packages/nocodb/src/schema/swagger.json

2
packages/nc-gui/components/account/ResetPassword.vue

@ -54,7 +54,7 @@ const passwordChange = async () => {
message.success(t('msg.success.passwordChanged')) message.success(t('msg.success.passwordChanged'))
signOut() await signOut()
navigateTo('/signin') navigateTo('/signin')
} }

4
packages/nc-gui/components/general/MiniSidebar.vue

@ -11,8 +11,8 @@ const route = useRoute()
const email = computed(() => user.value?.email ?? '---') const email = computed(() => user.value?.email ?? '---')
const logout = () => { const logout = async () => {
signOut() await signOut()
navigateTo('/signin') navigateTo('/signin')
} }
</script> </script>

18
packages/nc-gui/components/smartsheet/header/Cell.vue

@ -7,6 +7,7 @@ interface Props {
required?: boolean | number required?: boolean | number
hideMenu?: boolean hideMenu?: boolean
} }
const props = defineProps<Props>() const props = defineProps<Props>()
const hideMenu = toRef(props, 'hideMenu') const hideMenu = toRef(props, 'hideMenu')
@ -34,6 +35,12 @@ const closeAddColumnDropdown = () => {
columnOrder.value = null columnOrder.value = null
editColumnDropdown.value = false editColumnDropdown.value = false
} }
const openHeaderMenu = () => {
if (!isForm.value && isUIAllowed('edit-column')) {
editColumnDropdown.value = true
}
}
</script> </script>
<template> <template>
@ -44,10 +51,11 @@ const closeAddColumnDropdown = () => {
<SmartsheetHeaderCellIcon v-if="column" /> <SmartsheetHeaderCellIcon v-if="column" />
<span <span
v-if="column" v-if="column"
class="name cursor-pointer" class="name"
:class="{ 'cursor-pointer': !isForm && isUIAllowed('edit-column') }"
style="white-space: nowrap" style="white-space: nowrap"
:title="column.title" :title="column.title"
@dblclick="editColumnDropdown = true" @dblclick="openHeaderMenu"
>{{ column.title }}</span >{{ column.title }}</span
> >
@ -56,11 +64,7 @@ const closeAddColumnDropdown = () => {
<template v-if="!hideMenu"> <template v-if="!hideMenu">
<div class="flex-1" /> <div class="flex-1" />
<LazySmartsheetHeaderMenu <LazySmartsheetHeaderMenu v-if="!isForm && isUIAllowed('edit-column')" @add-column="addField" @edit="openHeaderMenu" />
v-if="!isForm && isUIAllowed('edit-column')"
@add-column="addField"
@edit="editColumnDropdown = true"
/>
</template> </template>
<a-dropdown <a-dropdown

2
packages/nc-gui/composables/useApi/interceptors.ts

@ -66,7 +66,7 @@ export function addAxiosInterceptors(api: Api<any>) {
}) })
}) })
.catch(async (error) => { .catch(async (error) => {
state.signOut() await state.signOut()
// todo: handle new user // todo: handle new user
navigateTo('/signIn') navigateTo('/signIn')

12
packages/nc-gui/composables/useGlobal/actions.ts

@ -3,9 +3,15 @@ import { message, useNuxtApp } from '#imports'
export function useGlobalActions(state: State): Actions { export function useGlobalActions(state: State): Actions {
/** Sign out by deleting the token from localStorage */ /** Sign out by deleting the token from localStorage */
const signOut: Actions['signOut'] = () => { const signOut: Actions['signOut'] = async () => {
state.token.value = null state.token.value = null
state.user.value = null state.user.value = null
try {
if (state.token.value) {
const nuxtApp = useNuxtApp()
await nuxtApp.$api.auth.signout()
}
} catch {}
} }
/** Sign in by setting the token in localStorage */ /** Sign in by setting the token in localStorage */
@ -38,9 +44,9 @@ export function useGlobalActions(state: State): Actions {
signIn(response.data.token) signIn(response.data.token)
} }
}) })
.catch((err) => { .catch(async (err) => {
message.error(err.message || t('msg.error.youHaveBeenSignedOut')) message.error(err.message || t('msg.error.youHaveBeenSignedOut'))
signOut() await signOut()
}) })
.finally(resolve) .finally(resolve)
}) })

4
packages/nc-gui/layouts/base.vue

@ -13,8 +13,8 @@ const hasSider = ref(false)
const sidebar = ref<HTMLDivElement>() const sidebar = ref<HTMLDivElement>()
const logout = () => { const logout = async () => {
signOut() await signOut()
navigateTo('/signin') navigateTo('/signin')
} }

4
packages/nc-gui/pages/[projectType]/[projectId]/index.vue

@ -70,8 +70,8 @@ const sidebar = ref()
const email = computed(() => user.value?.email ?? '---') const email = computed(() => user.value?.email ?? '---')
const logout = () => { const logout = async () => {
signOut() await signOut()
navigateTo('/signin') navigateTo('/signin')
} }

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

@ -57,7 +57,7 @@ const passwordChange = async () => {
message.success(t('msg.success.passwordChanged')) message.success(t('msg.success.passwordChanged'))
signOut() await signOut()
navigateTo('/signin') navigateTo('/signin')
} }

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

@ -1126,6 +1126,31 @@ export class Api<
...params, ...params,
}), }),
/**
* @description Clear refresh token from the database and cookie.
*
* @tags Auth
* @name Signout
* @summary Signout
* @request POST:/api/v1/auth/user/signout
* @response `200` `{
msg?: string,
}` OK
*/
signout: (params: RequestParams = {}) =>
this.request<
{
msg?: string;
},
any
>({
path: `/api/v1/auth/user/signout`,
method: 'POST',
format: 'json',
...params,
}),
/** /**
* @description Authenticate existing user with their email and password. Successful login will return a JWT access-token. * @description Authenticate existing user with their email and password. Successful login will return a JWT access-token.
* *

34
packages/nocodb/src/lib/meta/api/userApi/userApis.ts

@ -279,13 +279,15 @@ async function googleSignin(req, res, next) {
)(req, res, next); )(req, res, next);
} }
const REFRESH_TOKEN_COOKIE_KEY = 'refresh_token';
function setTokenCookie(res, token): void { function setTokenCookie(res, token): void {
// create http only cookie with refresh token that expires in 7 days // create http only cookie with refresh token that expires in 7 days
const cookieOptions = { const cookieOptions = {
httpOnly: true, httpOnly: true,
expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
}; };
res.cookie('refresh_token', token, cookieOptions); res.cookie(REFRESH_TOKEN_COOKIE_KEY, token, cookieOptions);
} }
async function me(req, res): Promise<any> { async function me(req, res): Promise<any> {
@ -485,7 +487,9 @@ async function refreshToken(req, res): Promise<any> {
return res.status(400).json({ msg: 'Missing refresh token' }); return res.status(400).json({ msg: 'Missing refresh token' });
} }
const user = await User.getByRefreshToken(req.cookies.refresh_token); const user = await User.getByRefreshToken(
req.cookies[REFRESH_TOKEN_COOKIE_KEY]
);
if (!user) { if (!user) {
return res.status(400).json({ msg: 'Invalid refresh token' }); return res.status(400).json({ msg: 'Invalid refresh token' });
@ -522,6 +526,30 @@ async function renderPasswordReset(req, res): Promise<any> {
} }
} }
// clear refresh token cookie and update user refresh token to null
const signout = async (req, res): Promise<any> => {
const resBody = { msg: 'Success' };
if (!req.cookies[REFRESH_TOKEN_COOKIE_KEY]) {
return res.json(resBody);
}
const user = await User.getByRefreshToken(
req.cookies[REFRESH_TOKEN_COOKIE_KEY]
);
if (!user) {
return res.json(resBody);
}
res.clearCookie(REFRESH_TOKEN_COOKIE_KEY);
await User.update(user.id, {
refresh_token: null,
});
res.json(resBody);
};
const mapRoutes = (router) => { const mapRoutes = (router) => {
// todo: old api - /auth/signup?tool=1 // todo: old api - /auth/signup?tool=1
router.post( router.post(
@ -534,6 +562,7 @@ const mapRoutes = (router) => {
getAjvValidatorMw('swagger.json#/components/schemas/SignInReq'), getAjvValidatorMw('swagger.json#/components/schemas/SignInReq'),
catchError(signin) catchError(signin)
); );
router.post('/auth/user/signout', catchError(signout));
router.get('/auth/user/me', extractProjectIdAndAuthenticate, catchError(me)); router.get('/auth/user/me', extractProjectIdAndAuthenticate, catchError(me));
router.post( router.post(
'/auth/password/forgot', '/auth/password/forgot',
@ -622,6 +651,7 @@ const mapRoutes = (router) => {
getAjvValidatorMw('swagger.json#/components/schemas/SignInReq'), getAjvValidatorMw('swagger.json#/components/schemas/SignInReq'),
catchError(signin) catchError(signin)
); );
router.post('/api/v1/auth/user/signout', catchError(signout));
router.get( router.get(
'/api/v1/auth/user/me', '/api/v1/auth/user/me',
extractProjectIdAndAuthenticate, extractProjectIdAndAuthenticate,

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

@ -95,6 +95,34 @@
"description": "Create a new user with provided email and password and first user is marked as super admin. " "description": "Create a new user with provided email and password and first user is marked as super admin. "
} }
}, },
"/api/v1/auth/user/signout": {
"post": {
"summary": "Signout",
"operationId": "auth-signout",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"msg": {
"type": "string"
}
}
}
}
}
}
},
"tags": [
"Auth"
],
"description": "Clear refresh token from the database and cookie."
},
"parameters": []
},
"/api/v1/auth/user/signin": { "/api/v1/auth/user/signin": {
"post": { "post": {
"summary": "Signin", "summary": "Signin",

Loading…
Cancel
Save