diff --git a/src/plugins/naive.plugin.ts b/src/plugins/naive.plugin.ts
index 981d787a..2a9ac821 100644
--- a/src/plugins/naive.plugin.ts
+++ b/src/plugins/naive.plugin.ts
@@ -53,9 +53,11 @@ import {
NTooltip,
NUpload,
NUploadDragger,
+ NCheckbox,
} from 'naive-ui';
const components = [
+ NCheckbox,
NDynamicInput,
NDatePicker,
NCode,
diff --git a/src/tools/chmod-calculator/chmod-calculator.service.test.ts b/src/tools/chmod-calculator/chmod-calculator.service.test.ts
new file mode 100644
index 00000000..fafb393f
--- /dev/null
+++ b/src/tools/chmod-calculator/chmod-calculator.service.test.ts
@@ -0,0 +1,68 @@
+import { expect, describe, it } from 'vitest';
+import { computeChmodOctalRepresentation } from './chmod-calculator.service';
+
+describe('chmod-calculator', () => {
+ describe('computeChmodOctalRepresentation', () => {
+ it('get the octal representation from permissions', () => {
+ expect(
+ computeChmodOctalRepresentation({
+ permissions: {
+ owner: { read: true, write: true, execute: true },
+ group: { read: true, write: true, execute: true },
+ public: { read: true, write: true, execute: true },
+ },
+ }),
+ ).to.eql('777');
+
+ expect(
+ computeChmodOctalRepresentation({
+ permissions: {
+ owner: { read: false, write: false, execute: false },
+ group: { read: false, write: false, execute: false },
+ public: { read: false, write: false, execute: false },
+ },
+ }),
+ ).to.eql('000');
+
+ expect(
+ computeChmodOctalRepresentation({
+ permissions: {
+ owner: { read: false, write: true, execute: false },
+ group: { read: false, write: true, execute: true },
+ public: { read: true, write: false, execute: true },
+ },
+ }),
+ ).to.eql('235');
+
+ expect(
+ computeChmodOctalRepresentation({
+ permissions: {
+ owner: { read: true, write: false, execute: false },
+ group: { read: false, write: true, execute: false },
+ public: { read: false, write: false, execute: true },
+ },
+ }),
+ ).to.eql('421');
+
+ expect(
+ computeChmodOctalRepresentation({
+ permissions: {
+ owner: { read: false, write: false, execute: true },
+ group: { read: false, write: true, execute: false },
+ public: { read: true, write: false, execute: false },
+ },
+ }),
+ ).to.eql('124');
+
+ expect(
+ computeChmodOctalRepresentation({
+ permissions: {
+ owner: { read: false, write: true, execute: false },
+ group: { read: false, write: true, execute: false },
+ public: { read: false, write: true, execute: false },
+ },
+ }),
+ ).to.eql('222');
+ });
+ });
+});
diff --git a/src/tools/chmod-calculator/chmod-calculator.service.ts b/src/tools/chmod-calculator/chmod-calculator.service.ts
new file mode 100644
index 00000000..89535519
--- /dev/null
+++ b/src/tools/chmod-calculator/chmod-calculator.service.ts
@@ -0,0 +1,17 @@
+import _ from 'lodash';
+import type { GroupPermissions, Permissions } from './chmod-calculator.types';
+
+export { computeChmodOctalRepresentation };
+
+function computeChmodOctalRepresentation({ permissions }: { permissions: Permissions }): string {
+ const permissionValue = { read: 4, write: 2, execute: 1 };
+
+ const getGroupPermissionValue = (permission: GroupPermissions) =>
+ _.reduce(permission, (acc, isPermSet, key) => acc + (isPermSet ? _.get(permissionValue, key, 0) : 0), 0);
+
+ return [
+ getGroupPermissionValue(permissions.owner),
+ getGroupPermissionValue(permissions.group),
+ getGroupPermissionValue(permissions.public),
+ ].join('');
+}
diff --git a/src/tools/chmod-calculator/chmod-calculator.types.ts b/src/tools/chmod-calculator/chmod-calculator.types.ts
new file mode 100644
index 00000000..d3dc915f
--- /dev/null
+++ b/src/tools/chmod-calculator/chmod-calculator.types.ts
@@ -0,0 +1,10 @@
+export type Scope = 'read' | 'write' | 'execute';
+export type Group = 'owner' | 'group' | 'public';
+
+export type GroupPermissions = {
+ [k in Scope]: boolean;
+};
+
+export type Permissions = {
+ [k in Group]: GroupPermissions;
+};
diff --git a/src/tools/chmod-calculator/chmod-calculator.vue b/src/tools/chmod-calculator/chmod-calculator.vue
new file mode 100644
index 00000000..31f8b9fd
--- /dev/null
+++ b/src/tools/chmod-calculator/chmod-calculator.vue
@@ -0,0 +1,83 @@
+
+
+
+
+
+ |
+ Owner (u) |
+ Group (g) |
+ Public (o) |
+
+
+
+
+
+
+
+
+ |
+
+
+
+
+
+ {{ octal }}
+
+
+
+
+
+
+
+
+
diff --git a/src/tools/chmod-calculator/index.ts b/src/tools/chmod-calculator/index.ts
new file mode 100644
index 00000000..7d299e42
--- /dev/null
+++ b/src/tools/chmod-calculator/index.ts
@@ -0,0 +1,22 @@
+import { FileInvoice } from '@vicons/tabler';
+import { defineTool } from '../tool';
+
+export const tool = defineTool({
+ name: 'Chmod calculator',
+ path: '/chmod-calculator',
+ description: 'Compute your chmod permissions and commands with this online chmod calculator.',
+ keywords: [
+ 'chmod',
+ 'calculator',
+ 'file',
+ 'permission',
+ 'files',
+ 'directory',
+ 'folder',
+ 'recursive',
+ 'generator',
+ 'octal',
+ ],
+ component: () => import('./chmod-calculator.vue'),
+ icon: FileInvoice,
+});
diff --git a/src/tools/index.ts b/src/tools/index.ts
index bc5192a4..60ad21d0 100644
--- a/src/tools/index.ts
+++ b/src/tools/index.ts
@@ -1,6 +1,7 @@
import { LockOpen } from '@vicons/tabler';
import type { ToolCategory } from './tool';
+import { tool as chmodCalculator } from './chmod-calculator';
import { tool as mimeTypes } from './mime-types';
import { tool as otpCodeGeneratorAndValidator } from './otp-code-generator-and-validator';
import { tool as base64FileConverter } from './base64-file-converter';
@@ -77,7 +78,7 @@ export const toolsByCategory: ToolCategory[] = [
{
name: 'Development',
icon: LockOpen,
- components: [gitMemo, randomPortGenerator, crontabGenerator, jsonViewer, sqlPrettify],
+ components: [gitMemo, randomPortGenerator, crontabGenerator, jsonViewer, sqlPrettify, chmodCalculator],
},
{
name: 'Math',