diff --git a/src/tools/chmod-calculator/chmod-calculator.service.test.ts b/src/tools/chmod-calculator/chmod-calculator.service.test.ts index a7f94ca8..1a994de8 100644 --- a/src/tools/chmod-calculator/chmod-calculator.service.test.ts +++ b/src/tools/chmod-calculator/chmod-calculator.service.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { computeChmodOctalRepresentation, computeChmodSymbolicRepresentation, computePermissionsFromChmodOctalRepresentation, computePermissionsFromChmodSymbolicRepresentation } from './chmod-calculator.service'; +import { computeChmodOctalRepresentation, computeChmodSymbolicRepresentation, computePermissionsFromChmodOctalRepresentation, computePermissionsFromChmodSymbolicRepresentation, computeUmaskRepresentation } from './chmod-calculator.service'; describe('chmod-calculator', () => { describe('computeChmodOctalRepresentation', () => { @@ -454,4 +454,106 @@ describe('chmod-calculator', () => { }); }); }); + + describe('computeUmaskRepresentation', () => { + it('get the umask from permissions', () => { + expect( + computeUmaskRepresentation({ + permissions: { + owner: { read: true, write: true, execute: true }, + group: { read: true, write: true, execute: true }, + public: { read: true, write: true, execute: true }, + flags: { setuid: false, setgid: false, stickybit: false }, + }, + }), + ).to.deep.eq({ + octal: '000', + symbolic: 'umask u=rwx,g=rwx,o=rwx', + }); + + expect( + computeUmaskRepresentation({ + permissions: { + owner: { read: false, write: false, execute: false }, + group: { read: false, write: false, execute: false }, + public: { read: false, write: false, execute: false }, + flags: { setuid: false, setgid: false, stickybit: false }, + }, + }), + ).to.deep.eq({ + octal: '777', + symbolic: 'umask u=,g=,o=', + }); + + expect( + computeUmaskRepresentation({ + permissions: { + owner: { read: false, write: true, execute: false }, + group: { read: false, write: true, execute: true }, + public: { read: true, write: false, execute: true }, + flags: { setuid: false, setgid: false, stickybit: false }, + }, + }), + ).to.deep.eq({ + octal: '542', + symbolic: 'umask u=w,g=wx,o=rx', + }); + + expect( + computeUmaskRepresentation({ + permissions: { + owner: { read: true, write: false, execute: false }, + group: { read: false, write: true, execute: false }, + public: { read: false, write: false, execute: true }, + flags: { setuid: false, setgid: false, stickybit: false }, + }, + }), + ).to.deep.eq({ + octal: '356', + symbolic: 'umask u=r,g=w,o=x', + }); + + expect( + computeUmaskRepresentation({ + permissions: { + owner: { read: false, write: false, execute: true }, + group: { read: false, write: true, execute: false }, + public: { read: true, write: false, execute: false }, + flags: { setuid: false, setgid: false, stickybit: false }, + }, + }), + ).to.deep.eq({ + octal: '653', + symbolic: 'umask u=x,g=w,o=r', + }); + + expect( + computeUmaskRepresentation({ + permissions: { + owner: { read: false, write: true, execute: false }, + group: { read: false, write: true, execute: false }, + public: { read: false, write: true, execute: false }, + flags: { setuid: false, setgid: false, stickybit: false }, + }, + }), + ).to.deep.eq({ + octal: '555', + symbolic: 'umask u=w,g=w,o=w', + }); + + expect( + computeUmaskRepresentation({ + permissions: { + owner: { read: false, write: false, execute: true }, + group: { read: false, write: true, execute: false }, + public: { read: true, write: false, execute: false }, + flags: { setuid: true, setgid: true, stickybit: true }, + }, + }), + ).to.deep.eq({ + octal: '653', + symbolic: 'umask u=x,g=w,o=r', + }); + }); + }); }); diff --git a/src/tools/chmod-calculator/chmod-calculator.service.ts b/src/tools/chmod-calculator/chmod-calculator.service.ts index 9a1ced4c..e8a069f6 100644 --- a/src/tools/chmod-calculator/chmod-calculator.service.ts +++ b/src/tools/chmod-calculator/chmod-calculator.service.ts @@ -1,7 +1,7 @@ import _ from 'lodash'; import type { GroupPermissions, Permissions, SpecialPermissions } from './chmod-calculator.types'; -export { computeChmodOctalRepresentation, computeChmodSymbolicRepresentation, computePermissionsFromChmodOctalRepresentation, computePermissionsFromChmodSymbolicRepresentation }; +export { computeUmaskRepresentation, computeChmodOctalRepresentation, computeChmodSymbolicRepresentation, computePermissionsFromChmodOctalRepresentation, computePermissionsFromChmodSymbolicRepresentation }; function computeChmodOctalRepresentation({ permissions }: { permissions: Permissions }): string { const permissionValue = { read: 4, write: 2, execute: 1 }; @@ -86,3 +86,30 @@ function computePermissionsFromChmodSymbolicRepresentation(symbolicPermissions: return computePermissionsFromChmodOctalRepresentation(octalString); } + +function computeUmaskRepresentation({ permissions }: { permissions: Permissions }): { + octal: string + symbolic: string +} { + const permissionValue = { read: 'r', write: 'w', execute: 'x' }; + const getGroupPermissionValue = (permission: GroupPermissions) => + _.reduce(permission, (acc, isPermSet, key) => acc + ((isPermSet ? _.get(permissionValue, key, '') : '')), ''); + + const symbolic = `umask u=${getGroupPermissionValue(permissions.owner)},g=${getGroupPermissionValue(permissions.group)},o=${getGroupPermissionValue(permissions.public)}`; + const octal = (0o777 - Number.parseInt( + computeChmodOctalRepresentation({ + permissions: + { + owner: permissions.owner, + group: permissions.group, + public: permissions.public, + flags: { setuid: false, setgid: false, stickybit: false }, + }, + }), 8)) + .toString(8) + .padStart(3, '0'); + + return { + symbolic, octal, + }; +} diff --git a/src/tools/chmod-calculator/chmod-calculator.vue b/src/tools/chmod-calculator/chmod-calculator.vue index ed7ec9cb..502f8491 100644 --- a/src/tools/chmod-calculator/chmod-calculator.vue +++ b/src/tools/chmod-calculator/chmod-calculator.vue @@ -2,7 +2,7 @@ import { useThemeVars } from 'naive-ui'; import InputCopyable from '../../components/InputCopyable.vue'; -import { computeChmodOctalRepresentation, computeChmodSymbolicRepresentation, computePermissionsFromChmodOctalRepresentation, computePermissionsFromChmodSymbolicRepresentation } from './chmod-calculator.service'; +import { computeChmodOctalRepresentation, computeChmodSymbolicRepresentation, computePermissionsFromChmodOctalRepresentation, computePermissionsFromChmodSymbolicRepresentation, computeUmaskRepresentation } from './chmod-calculator.service'; import type { Group, Scope } from './chmod-calculator.types'; import { useValidation } from '@/composable/validation'; @@ -81,6 +81,7 @@ watch( const octal = computed(() => computeChmodOctalRepresentation({ permissions: permissions.value })); const symbolic = computed(() => computeChmodSymbolicRepresentation({ permissions: permissions.value })); +const umask = computed(() => computeUmaskRepresentation({ permissions: permissions.value })); diff --git a/src/tools/chmod-calculator/index.ts b/src/tools/chmod-calculator/index.ts index 7d299e42..73e7d709 100644 --- a/src/tools/chmod-calculator/index.ts +++ b/src/tools/chmod-calculator/index.ts @@ -16,6 +16,7 @@ export const tool = defineTool({ 'recursive', 'generator', 'octal', + 'umask', ], component: () => import('./chmod-calculator.vue'), icon: FileInvoice,