Skip to content

Feat/custom note url #1699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

Nick0603
Copy link

Relatied issue: #1478

story:

  1. A created note
    image

  2. Click "Custom Note Url" in Menu
    image

  3. Type url you like and submit.
    image

  4. The url is customized and sync to all collaborators in real time.
    image

Details:

  1. That's ok if you want to set custom url for many times.
  • /serial_number -> /custom1 -> /custom2 -> /custom3

If some users browse the past url, they will redirect to latest one automatically.

  • /serial_number -> /custom3
  • /custom1 -> /custom3
  • /custom2 -> /custom3
  1. It will be blocked when the custom url is conflict with exist url.
    image

  2. But if the conflicted url is set by you in the past. You have right to set back.

  • /custom1 -> /custom2 -> /custom1
  1. Only the owner of note can edit custom url.
    image

@Nick0603 Nick0603 force-pushed the feature/custom-note-url branch from 8d6605f to 9ded54e Compare June 20, 2021 00:02
@jackycute jackycute requested review from a60814billy and Yukaii and removed request for a60814billy June 20, 2021 09:57
@Nick0603 Nick0603 force-pushed the feature/custom-note-url branch from 106e457 to d44be73 Compare June 20, 2021 18:27
@Yukaii Yukaii temporarily deployed to codimd-pr-1699 June 21, 2021 04:33 Inactive
const { Note, ArchivedNoteAlias, sequelize } = require('../models')
const realtime = require('../realtime/realtime')

const forbiddenAlias = ['', 'new', 'me', 'history', '403', '404', '500', 'config']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jackycute Also public/docs/*.md paths?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also config.forbiddenNoteIDs

@@ -223,6 +228,18 @@ module.exports = function (sequelize, DataTypes) {

Note.parseNoteId = function (noteId, callback) {
async.series({
parseNoteIdByArchivedAlias: function (_callback) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure about why we keep the previously used alias in track?
What if the archived alias you about to change has been used?

Copy link
Author

@Nick0603 Nick0603 Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not totally sure about why we keep the previously used alias in track?

My thought is to avoid some user saved the archived alias but can't connect the note.

What if the archived alias you about to change has been used?

The user just change one that not be used. Or we need to set the special and personal prefix for the alias?

Copy link
Member

@jackycute jackycute Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make this PR be more specific, it's better not to add this feature for redirecting previous alias to new one.
I suggest to remove this and by adding a notice alert area in the custom note url modal like: Notice: the previous custom note url will not be redirected to the new one, please take your own risk to change this. would help.

Copy link
Member

@a60814billy a60814billy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Nick0603,

Thanks for your contribution, there are some suggestions:

  1. In general, we use strict mode in backend.
  2. Do not mix different asynchronous paradigm in a procedure.
  3. Maybe we can fill-in alias url in modal if the note already setup an alias url.
  4. To avoid some vulnerability, we only support these character in customize url: lowercase
    letters, decimal digits, hyphen, underscore. And need check user input is valid both frontend and backend. Do not auto correct or filter out the input.
  5. Alias would be conflict with another nodeId, shortid

return alias.replace(/( |\/)/, '')
}

const asyncGetNote = async (originAliasOrNoteId) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have getNoteById function in note/index.js

Copy link
Author

@Nick0603 Nick0603 Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the getNoteById in note/index.js noget pure note row data.
I think controller or service should be choose the enough data to use.

But I also agree DRY is nice here, I will adjust it.

@hackmdio hackmdio deleted a comment from jackycute Jun 21, 2021
@@ -8,6 +8,7 @@ const { newCheckViewPermission, errorForbidden, responseCodiMD, errorNotFound, e
const { updateHistory, historyDelete } = require('../history')
const { actionPublish, actionSlide, actionInfo, actionDownload, actionPDF, actionGist, actionRevision, actionPandoc } = require('./noteActions')
const realtime = require('../realtime/realtime')
const serv = require('./service')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename service -> noteAlias, and consider using object destruction

Copy link
Author

@Nick0603 Nick0603 Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to make the service is for all note controller, so I think the naming noteAlias is not suitable.
And the service will contains the common logic in controller and easy for testing.

@Yukaii Yukaii temporarily deployed to codimd-pr-1699 June 21, 2021 15:11 Inactive
@Yukaii Yukaii temporarily deployed to codimd-pr-1699 June 21, 2021 15:55 Inactive
@Nick0603 Nick0603 force-pushed the feature/custom-note-url branch from 77c3b03 to 1ee19ed Compare June 21, 2021 19:40
@Yukaii Yukaii temporarily deployed to codimd-pr-1699 June 21, 2021 19:40 Inactive
@Nick0603
Copy link
Author

Hi @Nick0603,

Thanks for your contribution, there are some suggestions:

  1. In general, we use strict mode in backend.
  2. Do not mix different asynchronous paradigm in a procedure.
  3. Maybe we can fill-in alias url in modal if the note already setup an alias url.
  4. To avoid some vulnerability, we only support these character in customize url: lowercase
    letters, decimal digits, hyphen, underscore. And need check user input is valid both frontend and backend. Do not auto correct or filter out the input.
  5. Alias would be conflict with another nodeId, shortid
  1. OK, I will add the missed'use strict' line in code
  2. I don't really know the suggestion. Could you say more or give me a example.
  3. Yes, now the code can do it.
  4. OK
  5. OK, I use parseNoteIdAsync to validate the alias inputed by user. And then alias will be check by all aliases for a noteId includes 'note id '、'note short id'、'public/docs/*.md'

@Nick0603 Nick0603 force-pushed the feature/custom-note-url branch from 1ee19ed to 014790a Compare June 21, 2021 19:46
@Yukaii Yukaii temporarily deployed to codimd-pr-1699 June 21, 2021 19:46 Inactive
@a60814billy
Copy link
Member

Do not mix different asynchronous paradigm in a procedure.

For example:

The code mix two asynchronous paradigm, async/await and Promise.

const conflictNote = await exports.getNote(alias)
  .catch((err) => { throw err })

If you want to handle error in async/await, using try...catch statement.

try {
  const conflictNote = await exports.getNote(alias)
} catch ((err) => {
  throw err
})

But, the catch statement just rethrow the error, we can remove it.

const conflictNote = await exports.getNote(alias)

@Yukaii Yukaii temporarily deployed to codimd-pr-1699 June 22, 2021 18:01 Inactive

if (!note) {
logger.error('update note alias failed: note not found.')
return res.status(500).json({ status: 'error', message: 'Internal Error' })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return 404 for note not found

@@ -1266,6 +1277,62 @@ $('#revisionModalRevert').click(function () {
editor.setValue(revision.content)
ui.modal.revision.modal('hide')
})

// custom note url modal
const updateNoteUrl = (noteUrl = '') => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename: const updateNoteAliasUrl = (noteAliasUrl = '')
or const updateNoteCustomUrl = (noteCustomUrl = '')

return
}

updateNoteUrl(customUrl)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handle error in catch statement:

updateNoteUrl(customUrl)
  .then(({status}) => { .... })
  .catch((err) => {
    if (err.status === 400) .....
    ...
    showErrorMessage('Something wrong.')
  })

@a60814billy a60814billy changed the base branch from develop to feature/custom-note-url-base July 23, 2021 15:49
@a60814billy
Copy link
Member

Big thanks @Nick0603

@a60814billy a60814billy merged commit 829c961 into hackmdio:feature/custom-note-url-base Jul 23, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants