Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/thedevs-network/kutt.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzzwt <loophone@gmail.com>2021-12-03 04:56:07 +0300
committerzzwt <loophone@gmail.com>2021-12-03 04:56:07 +0300
commit9cbbade1aee3a42406141a7fdb9e56edbdb7de62 (patch)
tree3387d4e20f7ed22acc35a1834d2298a1c00b2130
parent0bc0e6629ba7d14bbe1ef0857ca9caf7110e953c (diff)
feat: change link password
-rw-r--r--client/components/LinksTable.tsx38
-rw-r--r--server/handlers/links.ts6
-rw-r--r--server/handlers/validators.ts7
-rw-r--r--server/queries/link.ts5
4 files changed, 49 insertions, 7 deletions
diff --git a/client/components/LinksTable.tsx b/client/components/LinksTable.tsx
index f1b2a26..0759ec0 100644
--- a/client/components/LinksTable.tsx
+++ b/client/components/LinksTable.tsx
@@ -116,6 +116,7 @@ interface EditForm {
address: string;
description?: string;
expire_in?: string;
+ password?: string;
}
const Row: FC<RowProps> = ({ index, link, setDeleteModal }) => {
@@ -123,7 +124,7 @@ const Row: FC<RowProps> = ({ index, link, setDeleteModal }) => {
const ban = useStoreActions(s => s.links.ban);
const edit = useStoreActions(s => s.links.edit);
const [banFormState, { checkbox }] = useFormState<BanForm>();
- const [editFormState, { text, label }] = useFormState<EditForm>(
+ const [editFormState, { text, label, password }] = useFormState<EditForm>(
{
target: link.target,
address: link.address,
@@ -132,7 +133,8 @@ const Row: FC<RowProps> = ({ index, link, setDeleteModal }) => {
? ms(differenceInMilliseconds(new Date(link.expire_in), new Date()), {
long: true
})
- : ""
+ : "",
+ password: ""
},
{ withIds: true }
);
@@ -175,6 +177,7 @@ const Row: FC<RowProps> = ({ index, link, setDeleteModal }) => {
} catch (err) {
setEditMessage(errorMessage(err));
}
+ editFormState.setField("password", "");
setEditLoading(false);
};
@@ -355,7 +358,7 @@ const Row: FC<RowProps> = ({ index, link, setDeleteModal }) => {
/>
</Flex>
</Col>
- <Col alignItems="flex-start">
+ <Col alignItems="flex-start" mr={3}>
<Text
{...label("address")}
as="label"
@@ -379,6 +382,33 @@ const Row: FC<RowProps> = ({ index, link, setDeleteModal }) => {
/>
</Flex>
</Col>
+ <Col alignItems="flex-start">
+ <Text
+ {...label("password")}
+ as="label"
+ mb={2}
+ fontSize={[14, 15]}
+ bold
+ >
+ Password
+ </Text>
+ <Flex as="form">
+ <TextInput
+ {...password({
+ name: "password"
+ })}
+ placeholder={link.password ? "●●●●●●●" : "Password..."}
+ autocomplete="off"
+ data-lpignore
+ pl={[3, 24]}
+ pr={[3, 24]}
+ placeholderSize={[13, 14]}
+ fontSize={[14, 15]}
+ height={[40, 44]}
+ width={[1, 210, 240]}
+ />
+ </Flex>
+ </Col>
</Flex>
<Flex alignItems="flex-start" width={1} mt={3}>
<Col alignItems="flex-start" mr={3}>
@@ -613,7 +643,7 @@ const LinksTable: FC = () => {
<H2 mb={3} light>
Recent shortened links.
</H2>
- <Table scrollWidth="800px">
+ <Table scrollWidth="1000px">
<thead>
<Tr justifyContent="space-between">
<Th flexGrow={1} flexShrink={1}>
diff --git a/server/handlers/links.ts b/server/handlers/links.ts
index a497cdd..857c857 100644
--- a/server/handlers/links.ts
+++ b/server/handlers/links.ts
@@ -108,8 +108,7 @@ export const create: Handler = async (req: CreateLinkReq, res) => {
};
export const edit: Handler = async (req, res) => {
- const { address, target, description, expire_in } = req.body;
-
+ const { address, target, description, expire_in, password } = req.body;
if (!address && !target) {
throw new CustomError("Should at least update one field.");
}
@@ -152,7 +151,8 @@ export const edit: Handler = async (req, res) => {
...(address && { address }),
...(description && { description }),
...(target && { target }),
- ...(expire_in && { expire_in })
+ ...(expire_in && { expire_in }),
+ ...(password && { password })
}
);
diff --git a/server/handlers/validators.ts b/server/handlers/validators.ts
index 635401b..7b5015c 100644
--- a/server/handlers/validators.ts
+++ b/server/handlers/validators.ts
@@ -145,6 +145,13 @@ export const editLink = [
.withMessage("URL is not valid.")
.custom(value => removeWww(URL.parse(value).host) !== env.DEFAULT_DOMAIN)
.withMessage(`${env.DEFAULT_DOMAIN} URLs are not allowed.`),
+ body("password")
+ .optional({ nullable: true, checkFalsy: true })
+ .custom(checkUser)
+ .withMessage("Only users can use this field.")
+ .isString()
+ .isLength({ min: 3, max: 64 })
+ .withMessage("Password length must be between 3 and 64."),
body("address")
.optional({ checkFalsy: true, nullable: true })
.isString()
diff --git a/server/queries/link.ts b/server/queries/link.ts
index 38c9a0e..e892df8 100644
--- a/server/queries/link.ts
+++ b/server/queries/link.ts
@@ -180,6 +180,11 @@ export const batchRemove = async (match: Match<Link>) => {
};
export const update = async (match: Partial<Link>, update: Partial<Link>) => {
+ if (update.password) {
+ const salt = await bcrypt.genSalt(12);
+ update.password = await bcrypt.hash(update.password, salt);
+ }
+
const links = await knex<Link>("links")
.where(match)
.update({ ...update, updated_at: new Date().toISOString() }, "*");