├── .editorconfig ├── .eslintrc.js ├── .github ├── dependabot.yml └── workflows │ ├── lint-eslint.yml │ ├── node.js.yml │ ├── php.yml │ └── semgrep.yml ├── .gitignore ├── .php-cs-fixer.dist.php ├── .well-known ├── security-policy.md └── security.txt ├── CHANGELOG.md ├── CONTRIBUTING.md ├── COPYING ├── LICENSE ├── Makefile ├── README.md ├── appinfo ├── info.xml └── routes.php ├── babel.config.js ├── composer.json ├── composer.lock ├── css └── workspace-style.css ├── docs ├── csv_user_import_feature │ ├── README.md │ └── users-import.csv ├── dev │ ├── CHANGELOG.md │ └── CODE_OF_CONDUCT.md └── user-guide │ ├── 1.X.X-to-2.X.X │ └── Documentation utilisateur de Workspace.pdf │ └── from-3.X.X │ ├── Documentation Workspace pour Gestionnaires Généraux - v3.0.pdf │ └── Documentation Workspace pour Gestionnaires d'Espaces - v3.0.pdf ├── img ├── 32x32.png ├── Workspace_white.svg ├── added_group_black.svg ├── added_group_white.svg ├── app.svg ├── color_picker.svg ├── group.png ├── member.png └── workspace_logo.png ├── l10n ├── cs.js ├── cs.json ├── en.js ├── fr.js └── fr.json ├── lib ├── AppInfo │ ├── Application.php │ └── Capabilities.php ├── Commands │ ├── Create.php │ └── Import.php ├── Controller │ ├── ConnectedGroupController.php │ ├── FileCSVController.php │ ├── GroupController.php │ ├── PageController.php │ ├── SpaceController.php │ └── WorkspaceController.php ├── Db │ ├── ConnectedGroup.php │ ├── GroupFoldersGroupsMapper.php │ ├── Space.php │ └── SpaceMapper.php ├── Exceptions │ ├── AbstractNotification.php │ ├── BadRequestException.php │ ├── CreateGroupException.php │ ├── CreateWorkspaceException.php │ ├── GroupException.php │ ├── GroupFolderFunctionException.php │ ├── Notifications │ │ ├── AbstractNotificationException.php │ │ ├── BadMimeType.php │ │ ├── EmailDoesntUniqueException.php │ │ ├── InvalidCsvFormatException.php │ │ ├── InvalidSeparatorCsvException.php │ │ └── UserDoesntExistException.php │ └── WorkspaceNameExistException.php ├── Files │ ├── BasicStreamInterface.php │ ├── Connection │ │ └── Terminal.php │ ├── Csv │ │ ├── CheckMimeType.php │ │ ├── CsvHeaderExtractorInterface.php │ │ ├── CsvParserInterface.php │ │ ├── CsvReader.php │ │ ├── CsvValidatorInterface.php │ │ ├── ImportUsers │ │ │ ├── Header.php │ │ │ ├── HeaderExtractor.php │ │ │ ├── HeaderValidator.php │ │ │ ├── Parser.php │ │ │ ├── Values.php │ │ │ └── ValuesValidator.php │ │ ├── Separator.php │ │ ├── SeparatorDetector.php │ │ └── StructureValidator.php │ ├── CsvAbstract.php │ ├── CsvInterface.php │ ├── FileInterface.php │ ├── FileUploader.php │ ├── MassiveWorkspaceCreation │ │ └── Csv.php │ └── NextcloudFile.php ├── Folder │ └── RootFolder.php ├── Group │ ├── AddedGroups │ │ └── AddedGroups.php │ ├── Admin │ │ ├── AdminGroup.php │ │ ├── AdminGroupManager.php │ │ └── AdminUserGroup.php │ ├── GroupBackend.php │ ├── SubGroups │ │ └── SubGroup.php │ └── User │ │ ├── UserGroup.php │ │ └── UserGroupManager.php ├── Helper │ └── GroupfolderHelper.php ├── Middleware │ ├── Exceptions │ │ └── AccessDeniedException.php │ ├── IsGeneralManagerMiddleware.php │ ├── IsSpaceAdminMiddleware.php │ └── WorkspaceAccessControlMiddleware.php ├── Migration │ ├── ChangeGroupnamesV300.php │ ├── FixMigrationToV300.php │ ├── RegisterWorkspaceUsersGroup.php │ └── Version0000Date20210615125333.php ├── Notifications │ └── ToastMessager.php ├── Response │ └── ErrorResponseFormatter.php ├── Roles.php ├── Service │ ├── ColorCode.php │ ├── Group │ │ ├── ConnectedGroupsService.php │ │ ├── GroupFolder │ │ │ └── GroupFolderManage.php │ │ ├── GroupFormatter.php │ │ ├── GroupsWorkspace.php │ │ ├── GroupsWorkspaceService.php │ │ ├── ManagersWorkspace.php │ │ ├── UserGroup.php │ │ └── WorkspaceManagerGroup.php │ ├── Slugger.php │ ├── SpaceService.php │ ├── User │ │ ├── UserFormatter.php │ │ └── UserWorkspace.php │ ├── UserService.php │ ├── Workspace │ │ └── WorkspaceCheckService.php │ └── WorkspaceService.php ├── Share │ └── Group │ │ ├── GroupMembersOnlyChecker.php │ │ └── ShareMembersOnlyFilter.php ├── Space │ └── SpaceManager.php ├── Upgrade │ ├── Upgrade.php │ ├── UpgradeFixV300V301.php │ ├── UpgradeInterface.php │ └── UpgradeV300.php ├── User │ ├── UserFinder.php │ ├── UserPresenceChecker.php │ └── UserSearcher.php ├── Users │ ├── Formatter │ │ └── UserImportedFormatter.php │ ├── UserFormatter.php │ └── UsersExistCheck.php └── Workspace │ └── WorkspaceChecker.php ├── package-lock.json ├── package.json ├── phpunit.integration.xml ├── phpunit.xml ├── screenshots ├── Workspace-1.png ├── Workspace-10.png ├── Workspace-2.png ├── Workspace-3-2.png ├── Workspace-4.png ├── Workspace-5.png ├── Workspace-6.png ├── Workspace-7.png ├── Workspace-8.png └── Workspace-9.png ├── scripts └── database_checker.php ├── src ├── AddUsersTabs.vue ├── AlertRemoveGroup.vue ├── App.vue ├── ButtonUploadLocalFile.vue ├── ButtonUploadShareFiles.vue ├── Error403.vue ├── Errors │ ├── BadCreateError.js │ ├── BadGetError.js │ └── Groupfolders │ │ ├── AddGroupToGroupfolderError.js │ │ ├── AddGroupToManageACLForGroupfolderError.js │ │ ├── BadCreateError.js │ │ ├── CheckGroupfolderNameError.js │ │ ├── EnableAclGroupfolderError.js │ │ ├── GetGroupfolderError.js │ │ └── RemoveGroupToManageACLForGroupfolderError.js ├── GroupDetails.vue ├── GroupMenuItem.vue ├── Home.vue ├── LeftSidebar.vue ├── LoadingUsers.vue ├── MenuItemSelector.vue ├── MultiSelectUsers.vue ├── RemoveSpace.vue ├── SelectConnectedGroups.vue ├── SpaceDetails.vue ├── SpaceMenuItem.vue ├── SpaceTable.vue ├── UserCard.vue ├── UserTable.vue ├── WorkspaceContent.vue ├── components │ └── Modals │ │ └── EditWorkspace.vue ├── constants.js ├── main.js ├── router.js ├── services │ ├── Groups │ │ ├── ManagerGroup.js │ │ └── UserGroup.js │ ├── Notifications │ │ └── NotificationError.js │ ├── groupfoldersService.js │ └── spaceService.js ├── store │ ├── actions.js │ ├── getters.js │ ├── index.js │ └── mutations.js └── tests │ ├── OC.js │ ├── __mocks__ │ ├── axios.js │ └── styleMock.js │ ├── jest.setup.js │ └── unit │ ├── addUsersTabs.test.js │ ├── groupfoldersService.test.js │ ├── spaceService.test.js │ ├── store.test.js │ └── workspaceContent.test.js ├── stylelint.config.js ├── templates └── index.php ├── tests ├── Integration │ └── AppTest.php ├── Unit │ ├── Controller │ │ └── PageControllerTest.php │ ├── Middleware │ │ └── WorkspaceAccessControlMiddlewareTest.php │ ├── Service │ │ ├── UserServiceTest.php │ │ └── Workspace │ │ │ └── WorkspaceCheckServiceTest.php │ └── Space │ │ └── SpaceManagerTest.php ├── bootstrap.php └── phpunit.unit.xml ├── webpack.config.js └── webpack.dev.config.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | 9 | [lib/**.php] 10 | indent_style = tab 11 | indent_size = 4 12 | 13 | [src/**.js] 14 | indent_style = tab 15 | indent_size = 2 16 | 17 | [src/**.vue] 18 | indent_style = tab 19 | indent_size = 2 20 | 21 | [css/**.css] 22 | indent_style = tab 23 | indent_size = 2 24 | 25 | [Makefile] 26 | indent_style = tab 27 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright Copyright (c) 2017 Arawa 3 | * 4 | * @author 2021 Baptiste Fotia 5 | * @author 2021 Cyrille Bollu 6 | * 7 | * @license GNU AGPL version 3 or any later version 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | module.exports = { 25 | extends: [ 26 | '@nextcloud', 27 | 'plugin:vue/recommended', 28 | ], 29 | rules: { 30 | // TODO: Search how to config it 31 | // https://eslint.vuejs.org/rules/first-attribute-linebreak.html 32 | 'vue/first-attribute-linebreak': 'off', 33 | 'vue/multi-word-component-names': 'off', 34 | }, 35 | } 36 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "npm" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | assignees: 9 | - "zak39" 10 | commit-message: 11 | prefix: "npm" 12 | labels: 13 | - "npm" 14 | - "dependencies" 15 | open-pull-requests-limit: 10 16 | pull-request-branch-name: 17 | separator: "/" 18 | 19 | - package-ecosystem: "composer" 20 | directory: "/" 21 | schedule: 22 | interval: "daily" 23 | assignees: 24 | - "zak39" 25 | commit-message: 26 | prefix: "Composer" 27 | labels: 28 | - "composer" 29 | - "dependencies" 30 | open-pull-requests-limit: 10 31 | pull-request-branch-name: 32 | separator: "/" -------------------------------------------------------------------------------- /.github/workflows/lint-eslint.yml: -------------------------------------------------------------------------------- 1 | # the workflow will run ESLint using `npm run lint` command 2 | name: ESLint CI 3 | 4 | on: 5 | push: 6 | branches: [ main, stable* ] 7 | pull_request: 8 | branches: [ main, stable* ] 9 | 10 | jobs: 11 | lint: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v2 16 | - name: Read package.json for npm engine version only 17 | uses: skjnldsv/read-package-engines-version-actions@v1.1 18 | id: versions 19 | with: 20 | fallbackNpm: '^9' 21 | fallbackNode: '^20' 22 | 23 | - name: Use Node.js ${{ steps.versions.outputs.nodeVersion }} 24 | uses: actions/setup-node@v2 25 | with: 26 | node-version: ${{ steps.versions.outputs.nodeVersion }} 27 | 28 | - name: Set up npm ${{ steps.versions.outputs.npmVersion }}" 29 | run: npm i -g npm@${{ steps.versions.outputs.npmVersion }} 30 | 31 | - name: Debug npm 32 | run: npm --version 33 | 34 | - name: Install all dependencies & build 35 | run: | 36 | npm ci -f 37 | npm run build --if-present 38 | 39 | - name: Lint 40 | run: npm run lint 41 | 42 | -------------------------------------------------------------------------------- /.github/workflows/node.js.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Node.js CI 5 | 6 | on: 7 | push: 8 | branches: [ main, stable* ] 9 | pull_request: 10 | branches: [ main, stable* ] 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v2 19 | 20 | - name: Read package.json for npm engine version only 21 | uses: skjnldsv/read-package-engines-version-actions@v1.1 22 | id: versions 23 | with: 24 | fallbackNpm: '^9' 25 | fallbackNode: '^20' 26 | 27 | - name: Use Node.js ${{ steps.versions.outputs.nodeVersion }} 28 | uses: actions/setup-node@v2 29 | with: 30 | node-version: ${{ steps.versions.outputs.nodeVersion }} 31 | 32 | - name: Set up npm ${{ steps.versions.outputs.npmVersion }}" 33 | run: npm i -g npm@${{ steps.versions.outputs.npmVersion }} 34 | 35 | - name: Debug npm 36 | run: npm --version 37 | 38 | - name: Install all dependencies & build 39 | run: | 40 | npm ci -f 41 | npm run build --if-present 42 | 43 | - name: Run all tests 44 | run: npm test 45 | -------------------------------------------------------------------------------- /.github/workflows/php.yml: -------------------------------------------------------------------------------- 1 | name: PHP Composer 2 | 3 | on: 4 | push: 5 | branches: [ main, stable* ] 6 | pull_request: 7 | branches: [ main, stable* ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | strategy: 14 | matrix: 15 | php-versions: [8.2] 16 | nextcloud-versions: ['stable28', 'master'] 17 | include: 18 | - php: 8.2 19 | nextcloud-version: master 20 | 21 | name: Nextcloud ${{ matrix.nextcloud-versions }} php${{ matrix.php-versions }} unit tests 22 | steps: 23 | - name: Set up php${{ matrix.php-versions }} 24 | uses: shivammathur/setup-php@master 25 | with: 26 | php-version: ${{ matrix.php-versions }} 27 | tools: composer:v2 28 | extensions: ctype,curl,dom,gd,iconv,intl,json,mbstring,openssl,posix,sqlite,xml,zip,gmp 29 | coverage: xdebug 30 | - name: Checkout Nextcloud 31 | run: git clone https://github.com/nextcloud/server.git --recursive --depth 1 -b ${{ matrix.nextcloud-versions }} nextcloud 32 | - name: Install Nextcloud 33 | run: php -f nextcloud/occ maintenance:install --database-name oc_autotest --database-user oc_autotest --admin-user admin --admin-pass admin --database sqlite --database-pass='' 34 | - name: Checkout workspace 35 | uses: actions/checkout@main 36 | with: 37 | path: nextcloud/apps/workspace 38 | - name: Validate composer.json and composer.lock 39 | working-directory: nextcloud/apps/workspace 40 | run: composer validate --strict 41 | - name: Install dependencies 42 | working-directory: nextcloud/apps/workspace 43 | run: composer install --prefer-dist --no-progress 44 | - name: Check coding standards 45 | working-directory: nextcloud/apps/workspace 46 | run: composer run-script cs:check 47 | - name: Run test suite 48 | working-directory: nextcloud/apps/workspace 49 | run: composer run-script test 50 | -------------------------------------------------------------------------------- /.github/workflows/semgrep.yml: -------------------------------------------------------------------------------- 1 | # Name of this GitHub Actions workflow. 2 | name: Semgrep 3 | 4 | on: 5 | # Scan changed files in PRs (diff-aware scanning): 6 | pull_request: {} 7 | # Scan mainline branches and report all findings: 8 | push: 9 | branches: ["main", "stable*"] 10 | # Schedule the CI job (this method uses cron syntax): 11 | schedule: 12 | - cron: '20 17 * * *' # Sets Semgrep to scan every day at 17:20 UTC. 13 | # It is recommended to change the schedule to a random time. 14 | 15 | jobs: 16 | semgrep: 17 | # User-definable name of this GitHub Actions job: 18 | name: Scan 19 | # If you are self-hosting, change the following `runs-on` value: 20 | runs-on: ubuntu-latest 21 | 22 | container: 23 | # A Docker image with Semgrep installed. Do not change this. 24 | image: returntocorp/semgrep 25 | 26 | # Skip any PR created by dependabot to avoid permission issues: 27 | if: (github.actor != 'dependabot[bot]') 28 | 29 | steps: 30 | # Fetch project source with GitHub Actions Checkout. 31 | - uses: actions/checkout@v3 32 | # Run the "semgrep ci" command on the command line of the docker image. 33 | - run: semgrep ci 34 | env: 35 | # Add the rules that Semgrep uses by setting the SEMGREP_RULES environment variable. 36 | SEMGREP_RULES: p/default # more at semgrep.dev/explore 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | vendor/ 3 | js/* 4 | build/ 5 | .php-cs-fixer.cache 6 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | getFinder() 12 | ->ignoreVCSIgnored(true) 13 | ->notPath('build') 14 | ->notPath('l10n') 15 | ->notPath('src') 16 | ->notPath('vendor') 17 | ->in(__DIR__); 18 | return $config; 19 | -------------------------------------------------------------------------------- /.well-known/security.txt: -------------------------------------------------------------------------------- 1 | Contact: mailto:security@arawa.fr 2 | Expires: 2024-03-09T09:00:00.000Z 3 | Preferred-Languages: en, fr 4 | Canonical: https://github.com/arawa/workspace/blob/main/.well-known/security.txt 5 | Policy: https://github.com/arawa/workspace/blob/main/.well-known/security-policy.txt 6 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | const babelConfig = require('@nextcloud/babel-config') 2 | 3 | module.exports = babelConfig 4 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "arawa/workspace", 3 | "description": "It's an interface to manage groupfolders with a group manage.", 4 | "type": "project", 5 | "license": "AGPL-3.0-or-later", 6 | "authors": [ 7 | { 8 | "name": "Baptiste Fotia" 9 | }, 10 | { 11 | "name": "Cyrille Bollu" 12 | } 13 | ], 14 | "require": { 15 | "php": ">=7.4 <=8.3" 16 | }, 17 | "require-dev": { 18 | "phpunit/phpunit": "^9.5", 19 | "nextcloud/coding-standard": "^1.1", 20 | "nextcloud/ocp": "^30.0", 21 | "symfony/console": "^6.3" 22 | }, 23 | "scripts": { 24 | "test": "phpunit -c tests/phpunit.unit.xml --fail-on-warning", 25 | "cs:check": "php-cs-fixer fix --dry-run --diff", 26 | "cs:fix": "php-cs-fixer fix" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /docs/csv_user_import_feature/README.md: -------------------------------------------------------------------------------- 1 | The .csv user import function lets you populate a Workspace with a large number of users in just one click. 2 | 3 | The expected file must be in .csv format, with commas as separators, UTF-8 encoding and CR, LF, CRLF carriage returns. 4 | 5 | It must contain two pieces of information per line: “user” and “role”. For users, the login or e-mail address (if unique) can be used. For roles, enter “u” or “user” to add a simple user and “wm” for a Workspace Manager. 6 | 7 | Here's a file that you can base upon to fill with the data corresponding to your instance : [users-import.csv](./users-import.csv) . 8 | -------------------------------------------------------------------------------- /docs/csv_user_import_feature/users-import.csv: -------------------------------------------------------------------------------- 1 | user,role 2 | pierre.quiroul,user 3 | awang,wm 4 | radjiv.velasquez,u 5 | christine.dupont@nextcloud.fr,wm 6 | jdoe@nextcloud.com,user 7 | -------------------------------------------------------------------------------- /docs/dev/CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct - Workspace 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to make participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to a positive environment for our 15 | community include: 16 | 17 | * Demonstrating empathy and kindness toward other people 18 | * Being respectful of differing opinions, viewpoints, and experiences 19 | * Giving and gracefully accepting constructive feedback 20 | * Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience 21 | * Focusing on what is best not just for us as individuals, but for the overall community 22 | 23 | Examples of unacceptable behavior include: 24 | 25 | * The use of sexualized language or imagery, and sexual attention or advances 26 | * Trolling, insulting or derogatory comments, and personal or political attacks 27 | * Public or private harassment 28 | * Publishing others' private information, such as a physical or email address, without their explicit permission 29 | * Other conduct which could reasonably be considered inappropriate in a professional setting 30 | 31 | ## Our Responsibilities 32 | 33 | Project maintainers are responsible for clarifying and enforcing our standards of 34 | acceptable behavior and will take appropriate and fair corrective action in 35 | response to any instances of unacceptable behavior. 36 | 37 | Project maintainers have the right and responsibility to remove, edit, or reject 38 | comments, commits, code, wiki edits, issues, and other contributions that are 39 | not aligned to this Code of Conduct, or to ban 40 | temporarily or permanently any contributor for other behaviors that they deem 41 | inappropriate, threatening, offensive, or harmful. 42 | 43 | ## Scope 44 | 45 | This Code of Conduct applies within all community spaces, and also applies when 46 | an individual is officially representing the community in public spaces. 47 | Examples of representing our community include using an official e-mail address, 48 | posting via an official social media account, or acting as an appointed 49 | representative at an online or offline event. 50 | 51 | ## Enforcement 52 | 53 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 54 | reported to the community leaders responsible for enforcement at [contact@arawa.fr](mailto:contact@arawa.fr). 55 | All complaints will be reviewed and investigated promptly and fairly. 56 | 57 | All community leaders are obligated to respect the privacy and security of the 58 | reporter of any incident. 59 | 60 | ## Attribution 61 | 62 | This Code of Conduct is adapted from the [Contributor Covenant](https://contributor-covenant.org/), version 63 | [1\.4](https://www.contributor-covenant.org/version/1/4/code-of-conduct/code_of_conduct.md) and 64 | [2\.0](https://www.contributor-covenant.org/version/2/0/code_of_conduct/code_of_conduct.md), 65 | and was generated by [contributing-gen](https://github.com/bttger/contributing-gen). 66 | -------------------------------------------------------------------------------- /docs/user-guide/1.X.X-to-2.X.X/Documentation utilisateur de Workspace.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/docs/user-guide/1.X.X-to-2.X.X/Documentation utilisateur de Workspace.pdf -------------------------------------------------------------------------------- /docs/user-guide/from-3.X.X/Documentation Workspace pour Gestionnaires Généraux - v3.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/docs/user-guide/from-3.X.X/Documentation Workspace pour Gestionnaires Généraux - v3.0.pdf -------------------------------------------------------------------------------- /docs/user-guide/from-3.X.X/Documentation Workspace pour Gestionnaires d'Espaces - v3.0.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/docs/user-guide/from-3.X.X/Documentation Workspace pour Gestionnaires d'Espaces - v3.0.pdf -------------------------------------------------------------------------------- /img/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/img/32x32.png -------------------------------------------------------------------------------- /img/Workspace_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Workspace 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/added_group_black.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Added Group 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/added_group_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Added Group 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /img/app.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | Artboard 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /img/color_picker.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /img/group.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/img/group.png -------------------------------------------------------------------------------- /img/member.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/img/member.png -------------------------------------------------------------------------------- /img/workspace_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/img/workspace_logo.png -------------------------------------------------------------------------------- /lib/AppInfo/Application.php: -------------------------------------------------------------------------------- 1 | 7 | * @license GNU AGPL version 3 or any later version 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | namespace OCA\Workspace\AppInfo; 25 | 26 | use OCA\Workspace\Db\SpaceMapper; 27 | use OCA\Workspace\Group\GroupBackend; 28 | use OCA\Workspace\Middleware\IsGeneralManagerMiddleware; 29 | use OCA\Workspace\Middleware\IsSpaceAdminMiddleware; 30 | use OCA\Workspace\Middleware\WorkspaceAccessControlMiddleware; 31 | use OCA\Workspace\Service\SpaceService; 32 | use OCA\Workspace\Service\UserService; 33 | use OCP\AppFramework\App; 34 | use OCP\AppFramework\Bootstrap\IBootContext; 35 | use OCP\AppFramework\Bootstrap\IBootstrap; 36 | use OCP\AppFramework\Bootstrap\IRegistrationContext; 37 | use OCP\AppFramework\Utility\IControllerMethodReflector; 38 | use OCP\IGroupManager; 39 | use OCP\IRequest; 40 | use OCP\IURLGenerator; 41 | 42 | class Application extends App implements IBootstrap { 43 | public const APP_ID = 'workspace'; 44 | 45 | public function __construct(array $urlParams = []) { 46 | parent::__construct(self::APP_ID, $urlParams); 47 | } 48 | 49 | public function register(IRegistrationContext $context): void { 50 | 51 | $context->registerService(WorkspaceAccessControlMiddleware::class, function ($c) { 52 | return new WorkspaceAccessControlMiddleware( 53 | $c->query(IURLGenerator::class), 54 | $c->query(UserService::class) 55 | ); 56 | }); 57 | 58 | $context->registerService(IsSpaceAdminMiddleware::class, function ($c) { 59 | return new IsSpaceAdminMiddleware( 60 | $c->query(IControllerMethodReflector::class), 61 | $c->query(IRequest::class), 62 | $c->query(UserService::class), 63 | $c->query(SpaceService::class) 64 | ); 65 | }); 66 | 67 | $context->registerService(IsGeneralManagerMiddleware::class, function ($c) { 68 | return new IsGeneralManagerMiddleware( 69 | $c->query(IControllerMethodReflector::class), 70 | $c->query(IRequest::class), 71 | $c->query(UserService::class) 72 | ); 73 | }); 74 | 75 | $context->registerMiddleware(WorkspaceAccessControlMiddleware::class); 76 | $context->registerMiddleware(IsSpaceAdminMiddleware::class); 77 | $context->registerMiddleware(IsGeneralManagerMiddleware::class); 78 | 79 | $context->registerCapability(Capabilities::class); 80 | } 81 | 82 | public function boot(IBootContext $context): void { 83 | // Unexplained BUG with autoload. Keep this line 84 | $context->getAppContainer()->query(SpaceMapper::class); 85 | 86 | $context->injectFn(function ( 87 | IGroupManager $groupManager, 88 | GroupBackend $groupBackend, 89 | ) { 90 | $groupManager->addBackend($groupBackend); 91 | }); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/AppInfo/Capabilities.php: -------------------------------------------------------------------------------- 1 | [ 23 | 'version' => $this->appManager->getAppVersion(Application::APP_ID), 24 | 'is_enabled' => $this->appManager->isEnabledForUser(Application::APP_ID), 25 | 'groupfolders_version' => $this->appManager->getAppVersion('groupfolders'), 26 | 'groupfolders_acl-inherit-per-user' => $this->config->getAppValue('groupfolders', 'acl-inherit-per-user', 'false') === 'true' 27 | ] 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/Controller/PageController.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Controller; 27 | 28 | use OCA\Workspace\AppInfo\Application; 29 | use OCA\Workspace\Service\UserService; 30 | use OCP\AppFramework\Controller; 31 | use OCP\AppFramework\Http\TemplateResponse; 32 | use OCP\IConfig; 33 | use OCP\Util; 34 | 35 | class PageController extends Controller { 36 | public function __construct( 37 | private UserService $userService, 38 | private IConfig $config, 39 | ) { 40 | } 41 | 42 | /** 43 | * Application's main page 44 | * 45 | * @NoAdminRequired 46 | * @NOCSRFRequired 47 | */ 48 | public function index(): TemplateResponse { 49 | Util::addScript(Application::APP_ID, 'workspace-main'); // js/workspace-main.js 50 | Util::addStyle(Application::APP_ID, 'workspace-style'); // css/workspace-style.css 51 | 52 | // templates/index.php 53 | return new TemplateResponse( 54 | 'workspace', 55 | 'index', 56 | [ 57 | 'isUserGeneralAdmin' => $this->userService->isUserGeneralAdmin(), 58 | 'canAccessApp' => $this->userService->canAccessApp(), 59 | 'aclInheritPerUser' => $this->config->getAppValue('groupfolders', 'acl-inherit-per-user', 'false') === 'true', 60 | ] 61 | ); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/Controller/SpaceController.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Controller; 27 | 28 | use OCA\Workspace\Db\SpaceMapper; 29 | use OCA\Workspace\Service\SpaceService; 30 | use OCP\AppFramework\Controller; 31 | use OCP\AppFramework\Http\DataResponse; 32 | use OCP\IRequest; 33 | 34 | class SpaceController extends Controller { 35 | public function __construct( 36 | IRequest $request, 37 | private $AppName, 38 | private SpaceMapper $spaceMapper, 39 | private SpaceService $spaceService, 40 | ) { 41 | parent::__construct($AppName, $request); 42 | } 43 | 44 | /** 45 | * @NoAdminRequired 46 | */ 47 | public function find(int $id): DataResponse { 48 | return new DataResponse($this->spaceService->find($id)); 49 | } 50 | 51 | /** 52 | * @NoAdminRequired 53 | */ 54 | public function findAll(): DataResponse { 55 | return new DataResponse($this->spaceService->findAll()); 56 | } 57 | 58 | /** 59 | * @NoAdminRequired 60 | * @SpaceAdminRequired 61 | */ 62 | public function updateColorCode(string $colorCode, int $spaceId): DataResponse { 63 | return new DataResponse($this->spaceService->updateColorCode($colorCode, (int)$spaceId)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/Db/ConnectedGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Db; 26 | 27 | use JsonSerializable; 28 | 29 | use OCP\AppFramework\Db\Entity; 30 | 31 | class ConnectedGroup extends Entity implements JsonSerializable { 32 | 33 | /** 34 | * @var integer 35 | */ 36 | protected $spaceId; 37 | 38 | /** 39 | * @var string 40 | */ 41 | protected $gid; 42 | 43 | public function __construct() { 44 | $this->addType('space_id', 'integer'); 45 | $this->addType('gid', 'string'); 46 | } 47 | 48 | public function jsonSerialize(): array { 49 | return [ 50 | 'space_id' => (int)$this->getSpaceId(), 51 | 'gid' => $this->getGid(), 52 | ]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/Db/Space.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Db; 27 | 28 | use JsonSerializable; 29 | 30 | use OCP\AppFramework\Db\Entity; 31 | 32 | class Space extends Entity implements JsonSerializable { 33 | /** @var integer */ 34 | protected $groupfolderId; 35 | 36 | /** @var string */ 37 | protected $spaceName; 38 | 39 | /** @var integer */ 40 | protected $spaceId; 41 | 42 | /** @var string */ 43 | protected $colorCode; 44 | 45 | public function __construct() { 46 | $this->addType('id', 'integer'); 47 | $this->addType('groupfolder_id', 'integer'); 48 | $this->addType('space_name', 'string'); 49 | $this->addType('color_code', 'string'); 50 | } 51 | 52 | /** 53 | * TODO: When it's wrote '$this->getId()', it prints well the 54 | * id when it created (POST). But, with GETs method, it has to 55 | * write $this->getSpaceId(). 56 | */ 57 | public function jsonSerialize(): array { 58 | return [ 59 | 'id' => (int)$this->getSpaceId(), 60 | 'groupfolder_id' => (int)$this->groupfolderId, 61 | 'name' => $this->spaceName, 62 | 'color_code' => $this->colorCode, 63 | ]; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/Exceptions/AbstractNotification.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Exceptions; 26 | 27 | abstract class AbstractNotification extends \Exception { 28 | public function __construct( 29 | private string $title, 30 | string $message, 31 | /** 32 | * @var integer from OCP\AppFramework\Http 33 | */ 34 | int $code, 35 | private array $argsMessage = [], 36 | ) { 37 | parent::__construct($message, $code); 38 | } 39 | 40 | public function getTitle(): string { 41 | return $this->title; 42 | } 43 | 44 | public function getArgsMessage(): array { 45 | return $this->argsMessage; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/Exceptions/BadRequestException.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Exceptions; 27 | 28 | use OCP\AppFramework\Http; 29 | 30 | class BadRequestException extends AbstractNotification { 31 | public function __construct($title, $message, $code = HTTP::STATUS_BAD_REQUEST, array $argsMessage = []) { 32 | parent::__construct(title: $title, message: $message, code: $code, argsMessage: $argsMessage); 33 | } 34 | 35 | public function getStatus(): int { 36 | return HTTP::STATUS_BAD_REQUEST; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/Exceptions/CreateGroupException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Exceptions; 26 | 27 | class CreateGroupException extends \Exception { 28 | public function __construct($message, $code = 0) { 29 | parent::__construct($message, $code); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/Exceptions/CreateWorkspaceException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Exceptions; 26 | 27 | class CreateWorkspaceException extends \Exception { 28 | public function __construct($message, $code = 0) { 29 | parent::__construct($message, $code); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/Exceptions/GroupException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Exceptions; 26 | 27 | class GroupException extends \Exception { 28 | public function __construct($message, $code = 0) { 29 | parent::__construct($message, $code); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/Exceptions/GroupFolderFunctionException.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Exceptions; 26 | 27 | class GroupFolderFunctionException extends \Exception { 28 | public function __construct(string $message, int $code = 0) { 29 | parent::__construct($message, $code); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /lib/Exceptions/Notifications/AbstractNotificationException.php: -------------------------------------------------------------------------------- 1 | title; 21 | } 22 | 23 | public function getArgsMessage(): array { 24 | return $this->argsMessage; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/Exceptions/Notifications/BadMimeType.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Exceptions; 26 | 27 | use OCP\AppFramework\Http; 28 | 29 | class WorkspaceNameExistException extends AbstractNotification { 30 | public function __construct($title, $message, $code = Http::STATUS_CONFLICT) { 31 | parent::__construct(title: $title, message: $message, code: $code); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/Files/BasicStreamInterface.php: -------------------------------------------------------------------------------- 1 | stream = fopen($path, 'r'); 18 | return $this->stream; 19 | } 20 | 21 | public function close(): bool { 22 | return fclose($this->stream); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/Files/Csv/CheckMimeType.php: -------------------------------------------------------------------------------- 1 | getMimetype() !== self::MIME_TYPE; 12 | } 13 | 14 | /** 15 | * @param array $file as $_FILE 16 | */ 17 | public function checkOnArray(array $file): bool { 18 | return $file['type'] !== self::MIME_TYPE; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/Files/Csv/CsvHeaderExtractorInterface.php: -------------------------------------------------------------------------------- 1 | open(); 17 | $headers = fgetcsv($handle, 1000, Separator::COMMA); 18 | $this->headers = array_map(function ($header) { 19 | return preg_replace('/[\x00-\x1F\x7F\x{200B}-\x{200D}\x{FEFF}]/u', '', trim($header)); 20 | }, $headers); 21 | $file->close(); 22 | } 23 | 24 | public function read(): \Generator { 25 | $handle = $this->file->open(); 26 | fgetcsv($handle, 1000, Separator::COMMA); 27 | 28 | try { 29 | while (($data = fgetcsv($handle, 1000, Separator::COMMA)) !== false) { 30 | yield array_combine($this->headers, $data); 31 | } 32 | } catch (\Exception $reason) { 33 | throw new \Exception($reason->getMessage()); 34 | } finally { 35 | $this->file->close(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/Files/Csv/CsvValidatorInterface.php: -------------------------------------------------------------------------------- 1 | $value) { 14 | $index = array_search($value, $needles); 15 | if ($index !== false) { 16 | return $index; 17 | } 18 | } 19 | return false; 20 | } 21 | 22 | /** 23 | * @throws \Exception when nothing header is found. 24 | */ 25 | public static function getHeaderName(array $needles, array $haystacks): string { 26 | $found = array_filter( 27 | $needles, 28 | fn ($needle) => in_array($needle, $haystacks) 29 | ); 30 | 31 | if (empty($found)) { 32 | throw new \Exception("The $needles needles is not present in $haystacks haystacks"); 33 | } 34 | 35 | $key = (string)array_values($found)[0]; 36 | 37 | return $key; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lib/Files/Csv/ImportUsers/HeaderValidator.php: -------------------------------------------------------------------------------- 1 | open()) !== false) { 12 | $tableHeader = fgetcsv($handle, 1000, ','); 13 | $tableHeader = array_map('strtolower', $tableHeader); 14 | 15 | $nameIndex = HeaderExtractor::getIndex(Header::DISPLAY_NAME, $tableHeader); 16 | $roleIndex = HeaderExtractor::getIndex(Header::ROLE, $tableHeader); 17 | 18 | $res = ($nameIndex !== false) && ($roleIndex !== false); 19 | } 20 | 21 | $file->close(); 22 | 23 | return $res; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /lib/Files/Csv/ImportUsers/Parser.php: -------------------------------------------------------------------------------- 1 | headers, Header::DISPLAY_NAME); 21 | $role = HeaderExtractor::getHeaderName($csvReader->headers, Header::ROLE); 22 | 23 | foreach ($csvReader->read() as $data) { 24 | $users[] = new UserImportedFormatter($data[$uid], $data[$role]); 25 | } 26 | 27 | return $users; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /lib/Files/Csv/ImportUsers/Values.php: -------------------------------------------------------------------------------- 1 | headers, Header::ROLE); 14 | foreach ($csvReader->read() as $data) { 15 | $role = strtolower($data[$index]); 16 | 17 | if (!in_array($role, Values::ROLES)) { 18 | return false; 19 | } 20 | } 21 | 22 | return $res; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /lib/Files/Csv/Separator.php: -------------------------------------------------------------------------------- 1 | open(); 12 | 13 | $firstLine = fread($handle, self::SIZE); 14 | 15 | $file->close(); 16 | 17 | return strpos($firstLine, Separator::COMMA) !== false; 18 | } 19 | 20 | public static function isCommaForAllFile(FileInterface $file): bool { 21 | $handle = $file->open(); 22 | $lines = fread($handle, $file->getSize()); 23 | $nbPipes = substr_count($lines, '|'); 24 | $nbSemiColons = substr_count($lines, ';'); 25 | 26 | $file->close(); 27 | 28 | if ( 29 | $nbPipes > 0 30 | || $nbSemiColons > 0 31 | ) { 32 | return false; 33 | } 34 | 35 | return true; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/Files/Csv/StructureValidator.php: -------------------------------------------------------------------------------- 1 | open(); 12 | $nbFieldsRequired = count(Header::FIELDS_REQUIRED); 13 | while (($data = fgetcsv($handle, 1000, Separator::COMMA)) !== false) { 14 | if (count($data) < $nbFieldsRequired) { 15 | return false; 16 | } 17 | } 18 | 19 | return true; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lib/Files/CsvAbstract.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Files; 26 | 27 | abstract class CsvAbstract { 28 | 29 | private const MIME_CSV_TYPES = [ 'text/csv', 'application/csv' ]; 30 | 31 | public function __construct() { 32 | } 33 | 34 | public function isCsvFile(string $path): bool { 35 | $mimetype = $this->getMimeType($path); 36 | 37 | if (in_array($mimetype, self::MIME_CSV_TYPES)) { 38 | return true; 39 | } 40 | 41 | return false; 42 | } 43 | 44 | public function getMimeType(string $path): string|false { 45 | return mime_content_type($path); 46 | } 47 | 48 | public function getIndex(array $haystack, array $needles): int|bool { 49 | $index = null; 50 | foreach ($haystack as $key => $value) { 51 | $index = array_search($value, $needles); 52 | if ($index !== false) { 53 | return $index; 54 | } 55 | } 56 | return false; 57 | } 58 | 59 | /** 60 | * @param resource $stream 61 | */ 62 | protected function next($stream): array|false { 63 | return fgetcsv($stream, 1000, ','); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lib/Files/CsvInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Files; 26 | 27 | interface CsvInterface { 28 | public function parser(string $path): array; 29 | public function hasProperHeader(string $path): bool; 30 | } 31 | -------------------------------------------------------------------------------- /lib/Files/FileInterface.php: -------------------------------------------------------------------------------- 1 | lineEnding = ini_get('auto_detect_line_endings'); 21 | ini_set('auto_detect_line_endings', true); 22 | $this->resource = fopen($this->path, 'r'); 23 | 24 | if (!$this->resource) { 25 | throw new \Exception('Something went wrong. Couldn\'t open the file.'); 26 | } 27 | 28 | return $this->resource; 29 | } 30 | 31 | public function close(): bool { 32 | ini_set('auto_detect_line_endings', $this->lineEnding); 33 | return fclose($this->resource); 34 | } 35 | 36 | public function getPath(): string { 37 | return $this->path; 38 | } 39 | 40 | public function getSize(): false|int|float { 41 | return filesize($this->path); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/Files/MassiveWorkspaceCreation/Csv.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Files\MassiveWorkspaceCreation; 26 | 27 | use OCA\Workspace\Files\Connection\Terminal; 28 | use OCA\Workspace\Files\CsvAbstract; 29 | use OCA\Workspace\Files\CsvInterface; 30 | 31 | /** 32 | * Allow to parse a csv file to create massive workspaces. 33 | */ 34 | class Csv extends CsvAbstract implements CsvInterface { 35 | 36 | public const WORKSPACE_FIELD = ['workspace-name', 'spacename']; 37 | public const USER_FIELD = ['user', 'uid', 'WorkspaceManager', 'workspace-manager']; 38 | public const QUOTA_FIELD = [ 'quota' ]; 39 | 40 | public function __construct( 41 | private Terminal $managerConnectionFile, 42 | ) { 43 | parent::__construct(); 44 | } 45 | 46 | public function parser(string $path): array { 47 | $stream = $this->managerConnectionFile->open($path); 48 | 49 | // ignore the header 50 | $tableHeader = $this->next($stream); 51 | 52 | $tableHeader = array_map('strtolower', $tableHeader); 53 | 54 | $workspaceIndex = $this->getIndex($this::WORKSPACE_FIELD, $tableHeader); 55 | $userIndex = $this->getIndex($this::USER_FIELD, $tableHeader); 56 | $quotaIndex = $this->getIndex($this::QUOTA_FIELD, $tableHeader); 57 | 58 | $data = []; 59 | 60 | while (($dataCsv = $this->next($stream)) !== false) { 61 | $userUid = $dataCsv[$userIndex]; 62 | 63 | if (empty($dataCsv[$userIndex])) { 64 | $userUid = null; 65 | } 66 | 67 | $quota = $dataCsv[$quotaIndex]; 68 | if (empty($dataCsv[$quotaIndex])) { 69 | $quota = '-3'; 70 | } 71 | 72 | $data[] = [ 73 | 'workspace_name' => $dataCsv[$workspaceIndex], 74 | 'user_uid' => $userUid, 75 | 'quota' => $quota 76 | ]; 77 | } 78 | 79 | $this->managerConnectionFile->close(); 80 | 81 | return $data; 82 | } 83 | 84 | public function hasProperHeader(string $path): bool { 85 | 86 | $res = true; 87 | 88 | $stream = $this->managerConnectionFile->open($path); 89 | 90 | // ignore the header 91 | $tableHeader = $this->next($stream); 92 | 93 | $tableHeader = array_map('strtolower', $tableHeader); 94 | 95 | $workspaceField = $this->getIndex(self::WORKSPACE_FIELD, $tableHeader); 96 | $uidField = $this->getIndex(self::USER_FIELD, $tableHeader); 97 | $quotaField = $this->getIndex(self::QUOTA_FIELD, $tableHeader); 98 | 99 | $res = ($workspaceField !== false) 100 | && ($uidField !== false) 101 | && ($quotaField !== false); 102 | 103 | $this->managerConnectionFile->close(); 104 | 105 | return $res; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /lib/Files/NextcloudFile.php: -------------------------------------------------------------------------------- 1 | lineEnding = ini_get('auto_detect_line_endings'); 23 | ini_set('auto_detect_line_endings', true); 24 | $store = $this->file->getStorage(); 25 | $this->resource = $store->fopen($this->file->getInternalPath(), 'r'); 26 | 27 | if (!$this->resource) { 28 | throw new \Exception('Something went wrong. Couldn\'t open the file.'); 29 | } 30 | 31 | return $this->resource; 32 | } 33 | 34 | public function close(): bool { 35 | ini_set('auto_detect_line_endings', $this->lineEnding); 36 | return fclose($this->resource); 37 | } 38 | 39 | public function getPath(): string { 40 | return $this->file->getInternalPath(); 41 | } 42 | 43 | public function getSize(): false|int|float { 44 | $store = $this->file->getStorage(); 45 | return $store->filesize($this->file->getInternalPath()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/Folder/RootFolder.php: -------------------------------------------------------------------------------- 1 | rootFolder->getMountPoint()->getNumericStorageId(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lib/Group/AddedGroups/AddedGroups.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Group\AddedGroups; 26 | 27 | use OCA\Workspace\Service\Group\ConnectedGroupsService; 28 | use OCA\Workspace\Service\Group\GroupFormatter; 29 | 30 | class AddedGroups { 31 | 32 | public function __construct( 33 | private ConnectedGroupsService $connectedGroupsService, 34 | ) { 35 | } 36 | 37 | public function get(array $gids): array { 38 | $addedGroups = []; 39 | foreach ($gids as $gid) { 40 | $addedToGroup = $this->connectedGroupsService->getConnectedGroupsToSpaceGroup($gid); 41 | if ($addedToGroup !== null) { 42 | $addedGroups = array_merge($addedGroups, $addedToGroup); 43 | } 44 | } 45 | 46 | return $addedGroups; 47 | } 48 | 49 | public function getGroupsFormatted(array $gids): array { 50 | return GroupFormatter::formatGroups($this->get($gids)); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/Group/Admin/AdminGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Group\Admin; 26 | 27 | use OCA\Workspace\Db\Space; 28 | use OCA\Workspace\Service\User\UserFormatter; 29 | use OCP\IGroupManager; 30 | use OCP\IUser; 31 | use Psr\Log\LoggerInterface; 32 | 33 | /** 34 | * This class represents a Workspace Manager (GE-) group. 35 | */ 36 | class AdminGroup { 37 | public const GID_PREFIX = 'SPACE-GE-'; 38 | 39 | public function __construct( 40 | private AdminUserGroup $adminUserGroup, 41 | private AdminGroupManager $adminGroupManager, 42 | private LoggerInterface $logger, 43 | private UserFormatter $userFormatter, 44 | private IGroupManager $groupManager, 45 | ) { 46 | } 47 | 48 | public function addUser(IUser $user, int $spaceId): bool { 49 | $group = $this->adminGroupManager->get(self::GID_PREFIX . $spaceId); 50 | $group->addUser($user); 51 | $this->adminUserGroup->addUser($user); 52 | 53 | return true; 54 | } 55 | 56 | public function removeUser(IUser $user, int $spaceId): void { 57 | $group = $this->groupManager->get(self::GID_PREFIX . $spaceId); 58 | $group->removeUser($user); 59 | } 60 | 61 | /** 62 | * @return IUser[] 63 | */ 64 | public function getUsers(int $spaceId): array { 65 | $group = $this->groupManager->get(self::GID_PREFIX . $spaceId); 66 | return $group->getUsers(); 67 | } 68 | 69 | public function getUsersFormatted(mixed $folderInfo, Space $space): array { 70 | $users = $this->getUsers($space->getSpaceId()); 71 | return $this->userFormatter->formatUsers($users, $folderInfo, (string)$space->getSpaceId()); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/Group/Admin/AdminGroupManager.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Group\Admin; 26 | 27 | use OCP\IGroup; 28 | use OCP\IGroupManager; 29 | 30 | /** 31 | * This class represents the manager of the 32 | * OCA\Workspace\Group\Admin\AdminGroup. 33 | */ 34 | class AdminGroupManager { 35 | public function __construct( 36 | public IGroupManager $groupManager, 37 | ) { 38 | } 39 | 40 | public function get(string $gid): IGroup { 41 | $group = $this->groupManager->get($gid); 42 | 43 | if (is_null($group)) { 44 | throw new \Exception("The $gid group does not exist."); 45 | } 46 | 47 | return $group; 48 | } 49 | 50 | public static function findWorkspaceManager(array $workspace): string { 51 | if (!array_key_exists('groups', $workspace)) { 52 | throw new \Exception('The "groups" key is not present in the $workspace variable.'); 53 | } 54 | 55 | $gids = array_keys($workspace['groups']); 56 | 57 | $groupname = array_values( 58 | array_filter( 59 | $gids, 60 | fn ($gid) => str_starts_with($gid, AdminGroup::GID_PREFIX) 61 | ) 62 | )[0]; 63 | 64 | return $groupname; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/Group/Admin/AdminUserGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Group\Admin; 26 | 27 | use OCP\IGroupManager; 28 | use OCP\IUser; 29 | use Psr\Log\LoggerInterface; 30 | 31 | /** 32 | * This class gathers all users from the 33 | * OCA\Workspace\Group\Admin\AdminGroup class 34 | * in the "WorkspacesManagers" group. 35 | */ 36 | class AdminUserGroup { 37 | public const GID = 'WorkspacesManagers'; 38 | 39 | public function __construct( 40 | private IGroupManager $groupManager, 41 | private LoggerInterface $logger, 42 | ) { 43 | } 44 | 45 | public function addUser(IUser $user): bool { 46 | $group = $this->groupManager->get(self::GID); 47 | 48 | if (is_null($group)) { 49 | throw new \Exception(sprintf('Impossible to to find the %s group.', self::GID)); 50 | } 51 | 52 | $group->addUser($user); 53 | 54 | return true; 55 | } 56 | 57 | public function removeUser(IUser $user): void { 58 | $this->logger->debug('The ' . $user->getUID() . 'User is not manager of any other workspace, removing it from the ' . self::GID . ' group.'); 59 | $workspaceUserGroup = $this->groupManager->get(self::GID); 60 | if ($workspaceUserGroup !== null) { 61 | $workspaceUserGroup->removeUser($user); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/Group/SubGroups/SubGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Group\SubGroups; 26 | 27 | use OCA\Workspace\Service\Group\GroupFormatter; 28 | use OCP\IGroupManager; 29 | use Psr\Log\LoggerInterface; 30 | 31 | class SubGroup { 32 | public function __construct( 33 | private IGroupManager $groupManager, 34 | private LoggerInterface $logger, 35 | ) { 36 | } 37 | 38 | public function get(array $gids): array { 39 | $groups = []; 40 | foreach ($gids as $gid) { 41 | $group = $this->groupManager->get($gid); 42 | if (is_null($group)) { 43 | $this->logger->warning( 44 | "Be careful, the $gid group does not exist in the oc_groups table." 45 | . ' The group is still present in the oc_group_folders_groups table.' 46 | . ' To fix this inconsistency, recreate the group using occ commands.' 47 | ); 48 | continue; 49 | } 50 | $groups[] = $group; 51 | } 52 | return $groups; 53 | } 54 | 55 | public function getGroupsFormatted(array $gids): array { 56 | return GroupFormatter::formatGroups($this->get($gids)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lib/Group/User/UserGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Group\User; 26 | 27 | use OCP\IGroupManager; 28 | use OCP\IUser; 29 | 30 | /** 31 | * This class represents a Workspace Manager (GE-) group. 32 | */ 33 | class UserGroup { 34 | public const GID_PREFIX = 'SPACE-U-'; 35 | 36 | public function __construct( 37 | private UserGroupManager $userGroupManager, 38 | private IGroupManager $groupManager, 39 | ) { 40 | } 41 | 42 | public function addUser(IUser $user, string $gid): bool { 43 | $group = $this->userGroupManager->get($gid); 44 | if ($group === null) { 45 | return false; 46 | } 47 | $group->addUser($user); 48 | 49 | return true; 50 | } 51 | 52 | public function count(int $spaceId): int { 53 | $usersGroup = $this->groupManager->get($this::GID_PREFIX . $spaceId); 54 | if ($usersGroup === null) { 55 | return 0; 56 | } 57 | return $usersGroup->count(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/Group/User/UserGroupManager.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Group\User; 26 | 27 | use OCP\IGroup; 28 | use OCP\IGroupManager; 29 | 30 | /** 31 | * This class represents the manager of the 32 | * OCA\Workspace\Group\User\UserGroup. 33 | */ 34 | class UserGroupManager { 35 | public function __construct( 36 | public IGroupManager $groupManager, 37 | ) { 38 | } 39 | 40 | public function get(string $gid): IGroup { 41 | $group = $this->groupManager->get($gid); 42 | 43 | if (is_null($group)) { 44 | throw new \Exception("The $gid group does not exist."); 45 | } 46 | 47 | return $group; 48 | } 49 | 50 | public static function findWorkspaceManager(array $workspace): string { 51 | if (!array_key_exists('groups', $workspace)) { 52 | throw new \Exception('The "groups" key is not present in the $workspace variable.'); 53 | } 54 | 55 | $gids = array_keys($workspace['groups']); 56 | 57 | $groupname = array_values( 58 | array_filter( 59 | $gids, 60 | fn ($gid) => str_starts_with($gid, UserGroup::GID_PREFIX) 61 | ) 62 | )[0]; 63 | 64 | return $groupname; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/Middleware/Exceptions/AccessDeniedException.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | declare(strict_types=1); 27 | 28 | namespace OCA\Workspace\Middleware\Exceptions; 29 | 30 | use OCP\AppFramework\Http; 31 | 32 | class AccessDeniedException extends \Exception { 33 | public function __construct() { 34 | parent::__construct('This user doesn\'t belong to General Manager group', Http::STATUS_FORBIDDEN); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/Middleware/IsGeneralManagerMiddleware.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Middleware; 27 | 28 | use Exception; 29 | use OCA\Workspace\Exceptions\AbstractNotification; 30 | use OCA\Workspace\Middleware\Exceptions\AccessDeniedException; 31 | use OCA\Workspace\Service\UserService; 32 | use OCP\AppFramework\Http; 33 | use OCP\AppFramework\Http\JSONResponse; 34 | use OCP\AppFramework\Middleware; 35 | use OCP\AppFramework\Utility\IControllerMethodReflector; 36 | use OCP\IRequest; 37 | 38 | class IsGeneralManagerMiddleware extends Middleware { 39 | public function __construct( 40 | private IControllerMethodReflector $reflector, 41 | private IRequest $request, 42 | private UserService $userService, 43 | ) { 44 | } 45 | 46 | public function beforeController($controller, $methodName): void { 47 | if ($this->reflector->hasAnnotation('GeneralManagerRequired')) { 48 | if (!$this->userService->isUserGeneralAdmin()) { 49 | throw new AccessDeniedException(); 50 | } 51 | } 52 | 53 | return; 54 | } 55 | 56 | public function afterException($controller, $methodName, Exception $exception): JSONResponse { 57 | if ($exception instanceof AccessDeniedException) { 58 | return new JSONResponse([ 59 | 'status' => 'forbidden', 60 | 'msg' => 'You are not allowed to perform this action' 61 | ], Http::STATUS_FORBIDDEN); 62 | } 63 | 64 | if ($exception instanceof AbstractNotification) { 65 | return new JSONResponse([ 66 | 'title' => $exception->getTitle(), 67 | 'statuscode' => $exception->getCode(), 68 | 'message' => $exception->getMessage(), 69 | 'args_message' => $exception->getArgsMessage() 70 | ], $exception->getCode()); 71 | } 72 | 73 | return new JSONResponse([ 74 | 'statuscode' => $exception->getCode(), 75 | 'message' => $exception->getMessage(), 76 | 'trace' => $exception->getTrace() 77 | ], $exception->getCode()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /lib/Middleware/IsSpaceAdminMiddleware.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Middleware; 27 | 28 | use OCA\Workspace\Exceptions\AbstractNotification; 29 | use OCA\Workspace\Middleware\Exceptions\AccessDeniedException; 30 | use OCA\Workspace\Service\SpaceService; 31 | use OCA\Workspace\Service\UserService; 32 | use OCP\AppFramework\Http; 33 | use OCP\AppFramework\Http\JSONResponse; 34 | use OCP\AppFramework\Middleware; 35 | use OCP\AppFramework\Utility\IControllerMethodReflector; 36 | use OCP\IRequest; 37 | 38 | class IsSpaceAdminMiddleware extends Middleware { 39 | public function __construct( 40 | private IControllerMethodReflector $reflector, 41 | private IRequest $request, 42 | private UserService $userService, 43 | private SpaceService $spaceService, 44 | ) { 45 | } 46 | 47 | public function beforeController($controller, $methodName): void { 48 | if ($this->reflector->hasAnnotation('SpaceAdminRequired')) { 49 | $spaceId = $this->request->getParam('spaceId'); 50 | if ($spaceId === null) { 51 | $data = $this->request->getParam('data'); 52 | $spaceId = $data ? $data['spaceId'] : null; 53 | } 54 | if ($spaceId === null) { 55 | throw new AccessDeniedException(); 56 | } 57 | $space = $this->spaceService->find($spaceId); 58 | if ($spaceId === null || $space === null || (!$this->userService->isSpaceManagerOfSpace($space->jsonSerialize()) && !$this->userService->isUserGeneralAdmin())) { 59 | throw new AccessDeniedException(); 60 | } 61 | } 62 | } 63 | 64 | public function afterException($controller, $methodName, \Exception $exception): JSONResponse { 65 | if ($exception instanceof AccessDeniedException) { 66 | return new JSONResponse([ 67 | 'status' => 'forbidden', 68 | 'msg' => 'You are not allowed to perform this action.' 69 | ], Http::STATUS_FORBIDDEN); 70 | } 71 | 72 | if ($exception instanceof AbstractNotification) { 73 | return new JSONResponse([ 74 | 'title' => $exception->getTitle(), 75 | 'statuscode' => $exception->getCode(), 76 | 'message' => $exception->getMessage(), 77 | 'args_message' => $exception->getArgsMessage() 78 | ], $exception->getCode()); 79 | } 80 | 81 | return new JSONResponse([ 82 | 'statuscode' => $exception->getCode(), 83 | 'message' => $exception->getMessage(), 84 | 'trace' => $exception->getTrace() 85 | ], $exception->getCode()); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lib/Middleware/WorkspaceAccessControlMiddleware.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Middleware; 27 | 28 | use OCA\Workspace\AppInfo\Application; 29 | use OCA\Workspace\Middleware\Exceptions\AccessDeniedException; 30 | use OCA\Workspace\Service\UserService; 31 | use OCP\AppFramework\Http\TemplateResponse; 32 | use OCP\AppFramework\Middleware; 33 | use OCP\IURLGenerator; 34 | use OCP\Util; 35 | 36 | class WorkspaceAccessControlMiddleware extends Middleware { 37 | public function __construct( 38 | private IURLGenerator $urlGenerator, 39 | private UserService $userService, 40 | ) { 41 | } 42 | 43 | public function beforeController($controller, $methodName): void { 44 | // Checks if user is member of the General managers group 45 | if ($this->userService->isUserGeneralAdmin()) { 46 | return; 47 | } 48 | 49 | // Checks if user if member of a Space managers group 50 | if ($this->userService->isSpaceManager()) { 51 | return; 52 | } 53 | 54 | throw new AccessDeniedException(); 55 | } 56 | 57 | // TODO: Find a solution to use this method. 58 | public function afterException($controller, $methodName, \Exception $exception): TemplateResponse { 59 | if ($exception instanceof AccessDeniedException) { 60 | Util::addScript(Application::APP_ID, 'workspace-main'); // js/workspace-main.js 61 | Util::addStyle(Application::APP_ID, 'workspace-style'); // css/workspace-style.css 62 | 63 | return new TemplateResponse('workspace', 'index', ['isUserGeneralAdmin' => $this->userService->isUserGeneralAdmin(), 'canAccessApp' => false ]); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/Migration/ChangeGroupnamesV300.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Migration; 26 | 27 | use OCA\Workspace\AppInfo\Application; 28 | use OCA\Workspace\Upgrade\Upgrade; 29 | use OCA\Workspace\Upgrade\UpgradeV300; 30 | use OCP\AppFramework\Services\IAppConfig as ServicesIAppConfig; 31 | use OCP\IAppConfig; 32 | use OCP\Migration\IOutput; 33 | use OCP\Migration\IRepairStep; 34 | use Psr\Log\LoggerInterface; 35 | 36 | class ChangeGroupnamesV300 implements IRepairStep { 37 | 38 | public const V300 = 300; 39 | 40 | public function __construct( 41 | private LoggerInterface $logger, 42 | private IAppConfig $appConfigManager, 43 | private ServicesIAppConfig $appConfig, 44 | private UpgradeV300 $upgradeV300, 45 | ) { 46 | $this->logger->debug('RegisterWorkspaceUsersGroup repair step initialised'); 47 | } 48 | 49 | public function getName(): string { 50 | return 'Creates the group of user allowed to use the application'; 51 | } 52 | 53 | public function run(IOutput $output): void { 54 | if (!$this->appConfigManager->hasKey(Application::APP_ID, 'DISPLAY_PREFIX_MANAGER_GROUP') 55 | && !$this->appConfigManager->hasKey(Application::APP_ID, 'DISPLAY_PREFIX_USER_GROUP')) { 56 | $this->appConfig->setAppValue('DISPLAY_PREFIX_MANAGER_GROUP', 'WM-'); 57 | $this->appConfig->setAppValue('DISPLAY_PREFIX_USER_GROUP', 'U-'); 58 | } 59 | 60 | if (!$this->appConfigManager->hasKey(Application::APP_ID, Upgrade::CONTROL_MIGRATION_V3)) { 61 | $this->appConfig->setAppValue(Upgrade::CONTROL_MIGRATION_V3, '0'); 62 | } 63 | 64 | $versionString = $this->appConfig->getAppValue('installed_version'); 65 | $versionSplitted = explode('.', $versionString); 66 | $version = intval(implode('', $versionSplitted)); 67 | 68 | $controlMigration = boolval($this->appConfig->getAppValue(Upgrade::CONTROL_MIGRATION_V3)); 69 | 70 | if ($version < self::V300 && $controlMigration === false) { 71 | $this->upgradeV300->upgrade(); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /lib/Migration/FixMigrationToV300.php: -------------------------------------------------------------------------------- 1 | logger->debug('FixMigrationToV300 repair step initialised'); 24 | 25 | } 26 | public function getName(): string { 27 | return 'Try to fix one problem to trigger the migration to v3.0.0 or 3.0.1'; 28 | } 29 | 30 | public function run(IOutput $output): void { 31 | $versionInstalled = $this->appConfig->getAppValue('installed_version'); 32 | $isBetween300And301 = version_compare($versionInstalled, '3.0.0', '>=') && version_compare($versionInstalled, '3.0.2', '<'); 33 | if (!$isBetween300And301) { 34 | return; 35 | } 36 | 37 | if (!$this->appConfigManager->hasKey(Application::APP_ID, Upgrade::CONTROL_MIGRATION_V3)) { 38 | $this->appConfig->setAppValue(Upgrade::CONTROL_MIGRATION_V3, '0'); 39 | } 40 | 41 | if (!$this->appConfigManager->hasKey(Application::APP_ID, 'DISPLAY_PREFIX_MANAGER_GROUP') 42 | && !$this->appConfigManager->hasKey(Application::APP_ID, 'DISPLAY_PREFIX_USER_GROUP')) { 43 | $this->appConfig->setAppValue('DISPLAY_PREFIX_MANAGER_GROUP', GroupsWorkspace::DEFAULT_DISPLAY_PREFIX_MANAGER_GROUP); 44 | $this->appConfig->setAppValue('DISPLAY_PREFIX_USER_GROUP', GroupsWorkspace::DEFAULT_DISPLAY_PREFIX_USER_GROUP); 45 | } 46 | 47 | $this->upgrade->upgrade(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/Migration/RegisterWorkspaceUsersGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Migration; 27 | 28 | use OCA\Workspace\Service\Group\ManagersWorkspace; 29 | use OCP\IGroupManager; 30 | use OCP\Migration\IOutput; 31 | use OCP\Migration\IRepairStep; 32 | use Psr\Log\LoggerInterface; 33 | 34 | class RegisterWorkspaceUsersGroup implements IRepairStep { 35 | public function __construct( 36 | private IGroupManager $groupManager, 37 | private LoggerInterface $logger, 38 | ) { 39 | $this->logger->debug('RegisterWorkspaceUsersGroup repair step initialised'); 40 | } 41 | 42 | public function getName(): string { 43 | return 'Creates the group of user allowed to use the application'; 44 | } 45 | 46 | public function run(IOutput $output): void { 47 | // The group already exists when we upgrade the app 48 | if (!$this->groupManager->groupExists(ManagersWorkspace::WORKSPACES_MANAGERS)) { 49 | $this->logger->debug('Group ' . ManagersWorkspace::WORKSPACES_MANAGERS . ' does not exist. Let\'s create it.'); 50 | $this->groupManager->createGroup(ManagersWorkspace::WORKSPACES_MANAGERS); 51 | } else { 52 | $this->logger->debug('Group ' . ManagersWorkspace::WORKSPACES_MANAGERS . ' already exists. No need to create it.'); 53 | } 54 | 55 | if (!$this->groupManager->groupExists(ManagersWorkspace::GENERAL_MANAGER)) { 56 | $this->logger->debug('Group ' . ManagersWorkspace::GENERAL_MANAGER . ' does not exist. Let\'s create it.'); 57 | $this->groupManager->createGroup(ManagersWorkspace::GENERAL_MANAGER); 58 | } else { 59 | $this->logger->debug('Group ' . ManagersWorkspace::GENERAL_MANAGER . ' already exists. No need to create it.'); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/Migration/Version0000Date20210615125333.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | declare(strict_types=1); 27 | 28 | namespace OCA\Workspace\Migration; 29 | 30 | use Closure; 31 | use OCP\DB\ISchemaWrapper; 32 | use OCP\Migration\IOutput; 33 | use OCP\Migration\SimpleMigrationStep; 34 | 35 | /** 36 | * Auto-generated migration step: Please modify to your needs! 37 | */ 38 | class Version0000Date20210615125333 extends SimpleMigrationStep { 39 | /** 40 | * @param IOutput $output 41 | * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` 42 | * @param array $options 43 | */ 44 | public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { 45 | } 46 | 47 | /** 48 | * @param IOutput $output 49 | * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` 50 | * @param array $options 51 | * @return null|ISchemaWrapper 52 | */ 53 | public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper { 54 | $schema = $schemaClosure(); 55 | 56 | if ($schema->hasTable('work_spaces')) { 57 | $schema->dropTable('work_spaces'); 58 | } 59 | 60 | $table = $schema->createTable('work_spaces'); 61 | 62 | $table->addColumn('space_id', 'bigint', [ 63 | 'autoincrement' => true, 64 | 'notnull' => true, 65 | 'length' => 6 66 | ]); 67 | 68 | $table->addColumn('groupfolder_id', 'bigint', [ 69 | 'autoincrement' => false, 70 | 'notnull' => true, 71 | 'length' => 6 72 | ]); 73 | 74 | $table->addColumn('color_code', 'string', [ 75 | 'notnull' => false, 76 | 'length' => 128, 77 | 'default' => null 78 | ]); 79 | 80 | $table->addColumn('space_name', 'string', [ 81 | 'notnull' => true, 82 | 'length' => 128, 83 | ]); 84 | 85 | $table->changeColumn('space_name', [ 86 | 'notnull' => true, 87 | 'length' => 4000 88 | ]); 89 | 90 | $table->setPrimaryKey([ 91 | 'space_id', 92 | 'groupfolder_id', 93 | ]); 94 | 95 | $table->addForeignKeyConstraint($schema->getTable('group_folders'), ['space_name'], ['mount_point'], ['onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'], 'fk_gi_sn_work_spaces'); 96 | $table->addForeignKeyConstraint($schema->getTable('group_folders'), ['groupfolder_id'], ['folder_id'], ['onDelete' => 'CASCADE', 'onUpdate' => 'CASCADE'], 'fk_gi_sn_work_spaces'); 97 | // $table->addForeignKeyConstraint($schema->getTable('group_folders'), ['groupfolder_id', 'space_name'], ['folder_id', 'mount_point'], [], 'fk_groupfolder_id_work_spaces'); 98 | 99 | return $schema; 100 | } 101 | 102 | /** 103 | * @param IOutput $output 104 | * @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` 105 | * @param array $options 106 | */ 107 | public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void { 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/Notifications/ToastMessager.php: -------------------------------------------------------------------------------- 1 | title; 14 | } 15 | 16 | public function getMessage(): string { 17 | return $this->message; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/Response/ErrorResponseFormatter.php: -------------------------------------------------------------------------------- 1 | getCode(); 25 | 26 | $dataMetadata = [ 27 | 'metadata' => [ 28 | 'status' => $code >= 200 && $code < 300 ? 'ok' : 'failure', 29 | 'status_code' => $code, 30 | 'message' => $exception->getMessage() 31 | ] 32 | ]; 33 | 34 | return $dataMetadata; 35 | } 36 | 37 | private static function createData(ToastMessager $notification): array { 38 | $dataEndUser = []; 39 | 40 | $dataEndUser['data'] = [ 41 | 'title' => $notification->getTitle(), 42 | 'message' => $notification->getMessage(), 43 | ]; 44 | 45 | return $dataEndUser; 46 | } 47 | 48 | private static function createDataException(\Exception $exception): array { 49 | $dataException = []; 50 | 51 | $dataException['exception'] = [ 52 | /** 53 | * string 54 | */ 55 | 'exception_message' => $exception->getMessage(), 56 | 57 | /** 58 | * int 59 | */ 60 | 'exception_code' => $exception->getCode(), 61 | 62 | /** 63 | * array 64 | */ 65 | 'exception_file' => [ 66 | 67 | /** 68 | * string - absolute path. 69 | */ 70 | 'name' => $exception->getFile(), 71 | 72 | /** 73 | * int - the line number of the file. 74 | */ 75 | 'line' => $exception->getLine(), 76 | ], 77 | 78 | /** 79 | * array 80 | */ 81 | 'exception_trace' => $exception->getTrace(), 82 | 83 | /** 84 | * string 85 | */ 86 | 'exception_trace_string' => $exception->getTraceAsString() 87 | ]; 88 | 89 | return $dataException; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /lib/Roles.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace; 26 | 27 | class Roles { 28 | public const Admin = 'wm'; 29 | public const User = 'user'; 30 | } 31 | -------------------------------------------------------------------------------- /lib/Service/ColorCode.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service; 26 | 27 | class ColorCode { 28 | public function generate(): string { 29 | // mt_rand() (MT - Mersenne Twister) is taller efficient than rand() function. 30 | return '#' . substr(md5(mt_rand()), 0, 6); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/Service/Group/GroupFolder/GroupFolderManage.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\Group; 26 | 27 | use OCA\Workspace\Service\Slugger; 28 | use OCP\IGroup; 29 | 30 | class GroupFormatter { 31 | /** 32 | * @param IGroup[] $groups 33 | * @return array [ 34 | * 'gid' => string, 35 | * 'displayName' => string, 36 | * 'types' => string[], 37 | * 'is_ldap' => boolean 38 | * ] 39 | */ 40 | public static function formatGroups(array $groups): array { 41 | $groupsFormat = []; 42 | 43 | foreach ($groups as $group) { 44 | 45 | $backendnames = $group->getBackendNames(); 46 | $backendnames = array_map( 47 | fn ($backendname) => strtoupper($backendname), 48 | $backendnames 49 | ); 50 | 51 | $usersCount = $group->count(); 52 | 53 | if (!UserGroup::isWorkspaceGroup($group)) { 54 | $users = $group->getUsers(); 55 | $users = array_filter($users, fn ($user) => $user->isEnabled()); 56 | $usersCount = count($users); 57 | } 58 | 59 | $groupsFormat[$group->getGID()] = [ 60 | 'gid' => $group->getGID(), 61 | 'displayName' => $group->getDisplayName(), 62 | 'types' => $group->getBackendNames(), 63 | 'usersCount' => $usersCount, 64 | 'slug' => Slugger::slugger($group->getGID()) 65 | ]; 66 | } 67 | 68 | return $groupsFormat; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/Service/Group/GroupsWorkspace.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\Group; 26 | 27 | use OCA\Workspace\Db\Space; 28 | use OCP\AppFramework\Services\IAppConfig; 29 | use OCP\IGroup; 30 | 31 | abstract class GroupsWorkspace { 32 | private const GID_SPACE_MANAGER = 'GE-'; 33 | private const GID_SPACE_USERS = 'U-'; 34 | private const GID_SPACE = 'SPACE-'; 35 | public const DEFAULT_DISPLAY_PREFIX_MANAGER_GROUP = 'WM-'; 36 | public const DEFAULT_DISPLAY_PREFIX_USER_GROUP = 'U-'; 37 | public const LEGACY_DISPLAY_PREFIX_LOCAL_GROUP = 'G-'; 38 | 39 | protected const PREFIX_GID_MANAGERS = self::GID_SPACE . self::GID_SPACE_MANAGER; 40 | protected const PREFIX_GID_USERS = self::GID_SPACE . self::GID_SPACE_USERS; 41 | 42 | protected static string $DISPLAY_PREFIX_MANAGER_GROUP; 43 | protected static string $DISPLAY_PREFIX_USER_GROUP; 44 | 45 | public function __construct(IAppConfig $appConfig) { 46 | self::$DISPLAY_PREFIX_MANAGER_GROUP = $appConfig->getAppValue('DISPLAY_PREFIX_MANAGER_GROUP', self::DEFAULT_DISPLAY_PREFIX_MANAGER_GROUP); 47 | self::$DISPLAY_PREFIX_USER_GROUP = $appConfig->getAppValue('DISPLAY_PREFIX_USER_GROUP', self::DEFAULT_DISPLAY_PREFIX_USER_GROUP); 48 | } 49 | 50 | public static function getDisplayPrefixManagerGroup(): string { 51 | return self::$DISPLAY_PREFIX_MANAGER_GROUP; 52 | } 53 | 54 | public static function getDisplayPrefixUserGroup(): string { 55 | return self::$DISPLAY_PREFIX_USER_GROUP; 56 | } 57 | 58 | public static function isWorkspaceUserGroupId(string $gid): bool { 59 | return str_starts_with($gid, self::PREFIX_GID_USERS); 60 | } 61 | 62 | public static function isWorkspaceAdminGroupId(string $gid): bool { 63 | return str_starts_with($gid, self::PREFIX_GID_MANAGERS); 64 | } 65 | 66 | public static function isWorkspaceGroup(IGroup $group) { 67 | return str_starts_with($group->getGID(), self::GID_SPACE) 68 | || str_starts_with($group->getDisplayName(), self::LEGACY_DISPLAY_PREFIX_LOCAL_GROUP); 69 | } 70 | 71 | /** 72 | * @return string - Just the GID with the spaceId. 73 | */ 74 | abstract public static function get(int $spaceId): string; 75 | 76 | abstract public static function getPrefix(): string; 77 | 78 | /** 79 | * Use the OCA\Workspace\Db\Space to get its spaceId and spaceName. 80 | */ 81 | abstract public function create(Space $space): IGroup; 82 | } 83 | -------------------------------------------------------------------------------- /lib/Service/Group/GroupsWorkspaceService.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\Group; 26 | 27 | use OCA\Workspace\Exceptions\GroupException; 28 | use OCP\IGroup; 29 | use OCP\IGroupManager; 30 | use OCP\IUser; 31 | 32 | class GroupsWorkspaceService { 33 | public function __construct( 34 | private IGroupManager $groupManager, 35 | ) { 36 | } 37 | 38 | /** 39 | * @throws GroupException 40 | */ 41 | public function getWorkspaceManagerGroup(string $spaceId): IGroup { 42 | $groupSpaceManager = $this->groupManager->get( 43 | WorkspaceManagerGroup::get($spaceId) 44 | ); 45 | 46 | if (is_null($groupSpaceManager)) { 47 | throw new GroupException('Error to get the workspace manage group relative to workspace.'); 48 | } 49 | 50 | return $groupSpaceManager; 51 | } 52 | 53 | /** 54 | * @throws GroupException 55 | */ 56 | public function getUserGroup(string $spaceId): IGroup { 57 | $groupUser = $this->groupManager->get( 58 | UserGroup::get($spaceId) 59 | ); 60 | 61 | if (is_null($groupUser)) { 62 | throw new GroupException('Error to get the workspace manage group relative to workspace.'); 63 | } 64 | 65 | return $groupUser; 66 | } 67 | 68 | /** 69 | * @return String[] 70 | */ 71 | public function getGroupsUserFromGroupfolder(IUser $user, array $groupfolder, string $spaceId): array { 72 | $groupsWorkspace = [ 73 | $this->getWorkspaceManagerGroup($spaceId)->getGID(), 74 | $this->getUserGroup($spaceId)->getGID() 75 | ]; 76 | $groups = []; 77 | foreach ($this->groupManager->getUserGroups($user) as $group) { 78 | if ( 79 | in_array($group->getGID(), array_keys($groupfolder['groups'])) 80 | || in_array($group->getGID(), $groupsWorkspace) 81 | ) { 82 | array_push($groups, $group->getGID()); 83 | } 84 | } 85 | 86 | return $groups; 87 | } 88 | 89 | /** 90 | * @param IUser[] $users 91 | */ 92 | public function transferUsersToGroup(array $users, IGroup $group): void { 93 | if (is_null($group)) { 94 | throw new GroupException('Error parameter, $group is null.'); 95 | } 96 | 97 | foreach ($users as $user) { 98 | $group->addUser($user); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /lib/Service/Group/ManagersWorkspace.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\Group; 26 | 27 | class ManagersWorkspace { 28 | public const WORKSPACES_MANAGERS = 'WorkspacesManagers'; 29 | public const GENERAL_MANAGER = 'GeneralManager'; 30 | } 31 | -------------------------------------------------------------------------------- /lib/Service/Group/UserGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\Group; 26 | 27 | use OCA\Workspace\Db\Space; 28 | use OCA\Workspace\Exceptions\CreateGroupException; 29 | use OCP\AppFramework\Http; 30 | use OCP\AppFramework\Services\IAppConfig; 31 | use OCP\IGroup; 32 | use OCP\IGroupManager; 33 | 34 | class UserGroup extends GroupsWorkspace { 35 | private IGroupManager $groupManager; 36 | 37 | public function __construct(IGroupManager $groupManager, IAppConfig $appConfig) { 38 | parent::__construct($appConfig); 39 | $this->groupManager = $groupManager; 40 | } 41 | 42 | public static function get(int $spaceId): string { 43 | return self::PREFIX_GID_USERS . $spaceId; 44 | } 45 | 46 | public static function getPrefix(): string { 47 | return self::PREFIX_GID_USERS; 48 | } 49 | 50 | public function create(Space $space): IGroup { 51 | $group = $this->groupManager->createGroup(self::PREFIX_GID_USERS . $space->getId()); 52 | 53 | if (is_null($group)) { 54 | throw new CreateGroupException('Error to create a Space Manager group.', Http::STATUS_CONFLICT); 55 | } 56 | 57 | $group->setDisplayName(self::getDisplayPrefixUserGroup() . $space->getSpaceName()); 58 | 59 | return $group; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/Service/Group/WorkspaceManagerGroup.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\Group; 26 | 27 | use OCA\Workspace\Db\Space; 28 | use OCA\Workspace\Exceptions\CreateGroupException; 29 | use OCP\AppFramework\Http; 30 | use OCP\AppFramework\Services\IAppConfig; 31 | use OCP\IGroup; 32 | use OCP\IGroupManager; 33 | 34 | class WorkspaceManagerGroup extends GroupsWorkspace { 35 | private IGroupManager $groupManager; 36 | 37 | public function __construct(IGroupManager $groupManager, IAppConfig $appConfig) { 38 | parent::__construct($appConfig); 39 | $this->groupManager = $groupManager; 40 | } 41 | 42 | public static function get(int $spaceId): string { 43 | return self::PREFIX_GID_MANAGERS . $spaceId; 44 | } 45 | 46 | public static function getPrefix(): string { 47 | return self::PREFIX_GID_MANAGERS; 48 | } 49 | 50 | public function create(Space $space): IGroup { 51 | $group = $this->groupManager->createGroup(self::PREFIX_GID_MANAGERS . $space->getId()); 52 | 53 | if (is_null($group)) { 54 | throw new CreateGroupException('Error to create a Space Manager group.', Http::STATUS_CONFLICT); 55 | } 56 | 57 | $group->setDisplayName(self::getDisplayPrefixManagerGroup() . $space->getSpaceName()); 58 | 59 | return $group; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lib/Service/Slugger.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Service; 27 | 28 | use OCA\Workspace\BadRequestException; 29 | use OCA\Workspace\Db\Space; 30 | use OCA\Workspace\Db\SpaceMapper; 31 | use OCP\IGroupManager; 32 | 33 | class SpaceService { 34 | public function __construct( 35 | private IGroupManager $groupManager, 36 | private SpaceMapper $spaceMapper, 37 | ) { 38 | } 39 | 40 | public function findAll(): array { 41 | return $this->spaceMapper->findAll(); 42 | } 43 | 44 | public function find($id): Space { 45 | return $this->spaceMapper->find($id); 46 | } 47 | 48 | /** 49 | * @deprecated 50 | * @see WorkspaceController->destroy(). 51 | */ 52 | public function delete(int $id): mixed { 53 | return $this->spaceMapper->deleteSpace($id); 54 | } 55 | 56 | /** 57 | * @param $spaceName 58 | * @return Space 59 | * @throws BadRequestException 60 | * @todo to debug this part 61 | */ 62 | public function create(string $spaceName, int $folderId): Space { 63 | $space = new Space(); 64 | $space->setSpaceName($spaceName); 65 | $space->setGroupfolderId($folderId); 66 | $space->setColorCode('#' . substr(md5(mt_rand()), 0, 6)); // mt_rand() (MT - Mersenne Twister) is taller efficient than rand() function. 67 | $this->spaceMapper->insert($space); 68 | return $space; 69 | } 70 | 71 | /** 72 | * 73 | */ 74 | public function updateSpaceName(string $newSpaceName, int $spaceId) { 75 | return $this->spaceMapper->updateSpaceName($newSpaceName, $spaceId); 76 | } 77 | 78 | public function updateColorCode(string $colorCode, int $spaceId): Space { 79 | return $this->spaceMapper->updateColorCode($colorCode, $spaceId); 80 | } 81 | 82 | public function checkSpaceNameExist(string $spacename): bool { 83 | $checkSpacename = $this->spaceMapper->checkSpaceNameExist($spacename); 84 | 85 | if (!is_bool($checkSpacename)) { 86 | if (array_key_exists('space_name', $checkSpacename)) { 87 | return true; 88 | } 89 | } 90 | 91 | return false; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /lib/Service/User/UserFormatter.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\User; 26 | 27 | use OCA\Workspace\Roles; 28 | use OCA\Workspace\Service\Group\ConnectedGroupsService; 29 | use OCA\Workspace\Service\Group\GroupsWorkspaceService; 30 | use OCA\Workspace\Service\Group\UserGroup; 31 | use OCP\IGroupManager; 32 | use OCP\IURLGenerator; 33 | use OCP\IUser; 34 | 35 | class UserFormatter { 36 | public function __construct( 37 | private GroupsWorkspaceService $groupsWorkspace, 38 | private IGroupManager $groupManager, 39 | private ConnectedGroupsService $connectedGroupsService, 40 | private IURLGenerator $urlGenerator, 41 | private UserGroup $userGroup, 42 | ) { 43 | } 44 | 45 | /** 46 | * @param IUser[] $users 47 | */ 48 | public function formatUsers(array $users, array $groupfolder, string $spaceId): array { 49 | $groupWorkspaceManager = $this->groupsWorkspace->getWorkspaceManagerGroup($spaceId); 50 | $spaceUserGid = UserGroup::get($spaceId); 51 | 52 | $usersFormatted = []; 53 | foreach ($users as $user) { 54 | if ($groupWorkspaceManager->inGroup($user)) { 55 | $role = Roles::Admin; 56 | } else { 57 | $role = Roles::User; 58 | } 59 | 60 | $isStrictSpaceUser = $this->connectedGroupsService->isStrictSpaceUser($user->getUID(), $spaceUserGid); 61 | 62 | $usersFormatted[$user->getUID()] = [ 63 | 'uid' => $user->getUID(), 64 | 'name' => $user->getDisplayName(), 65 | 'email' => $user->getEmailAddress(), 66 | 'subtitle' => $user->getEmailAddress(), 67 | 'groups' => $this->groupsWorkspace->getGroupsUserFromGroupfolder($user, $groupfolder, $spaceId), 68 | 'is_connected' => !$isStrictSpaceUser, 69 | 'profile' => $this->urlGenerator->linkToRouteAbsolute('core.ProfilePage.index', ['targetUserId' => $user->getUID()]), 70 | 'role' => $role 71 | ]; 72 | } 73 | 74 | return $usersFormatted; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/Service/User/UserWorkspace.php: -------------------------------------------------------------------------------- 1 | groupManager->get($groupName); 23 | if ($o_group !== null) { 24 | $users[] = $o_group->getUsers(); 25 | } 26 | } 27 | 28 | $usersMerged = array_merge([], ...$users); 29 | 30 | return $usersMerged; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/Service/Workspace/WorkspaceCheckService.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Service\Workspace; 26 | 27 | use OCA\Workspace\Exceptions\BadRequestException; 28 | use OCA\Workspace\Service\SpaceService; 29 | 30 | class WorkspaceCheckService { 31 | 32 | public const CHARACTERS_SPECIAL = '/:*?"<>|\\'; 33 | 34 | public function __construct( 35 | private SpaceService $spaceService, 36 | ) { 37 | } 38 | 39 | /** 40 | * Check if the space name contains specials characters or a blank into the end its name. 41 | * @param string $spacename 42 | * @throws BadRequestException 43 | */ 44 | public function containSpecialChar(string $spacename): bool { 45 | if (preg_match(sprintf('/[%s]/', preg_quote(self::CHARACTERS_SPECIAL, '/')), $spacename)) { 46 | return true; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | 53 | /** 54 | * Check if the space name exist in groupfolders or workspace 55 | */ 56 | public function isExist(string $spacename): bool { 57 | if ($this->spaceService->checkSpaceNameExist($spacename)) { 58 | return true; 59 | } 60 | 61 | return false; 62 | } 63 | 64 | public function spacenamesIsDuplicated(array $spaces): bool { 65 | $workspaceNames = []; 66 | 67 | foreach ($spaces as $space) { 68 | $workspaceNames[] = $space['workspace_name']; 69 | } 70 | 71 | $workspaceNamesDiff = array_values( 72 | array_diff_assoc($workspaceNames, array_unique($workspaceNames)) 73 | ); 74 | 75 | return !empty($workspaceNamesDiff); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/Share/Group/GroupMembersOnlyChecker.php: -------------------------------------------------------------------------------- 1 | shareManager->shareWithGroupMembersOnly(); 19 | } 20 | 21 | public function groupsExcludeSelected(): bool { 22 | if ( 23 | method_exists( 24 | $this->shareManager, 25 | 'shareWithGroupMembersOnlyExcludeGroupsList' 26 | ) 27 | ) { 28 | return $this->shareManager->shareWithGroupMembersOnly() 29 | && !empty($this->shareManager->shareWithGroupMembersOnlyExcludeGroupsList()); 30 | } 31 | 32 | return false; 33 | } 34 | 35 | public function checkMemberInGroupExcluded(): bool { 36 | $excludedGroups = $this->shareManager->shareWithGroupMembersOnlyExcludeGroupsList(); 37 | 38 | $userSession = $this->userSession->getUser(); 39 | $uid = $userSession->getUID(); 40 | 41 | foreach ($excludedGroups as $gid) { 42 | if ($this->groupManager->isInGroup($uid, $gid)) { 43 | return true; 44 | } 45 | } 46 | 47 | return false; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/Share/Group/ShareMembersOnlyFilter.php: -------------------------------------------------------------------------------- 1 | Share > Restrict users to only share with users in their groups > Ingore the following groups when cheking group membership`). 24 | */ 25 | public function excludeGroupsList(array $users): array { 26 | $usersNotExclude = []; 27 | 28 | if (method_exists($this->shareManager, 'shareWithGroupMembersOnlyExcludeGroupsList')) { 29 | $excludedGroups = $this->shareManager->shareWithGroupMembersOnlyExcludeGroupsList(); 30 | $userSession = $this->userSession->getUser(); 31 | $groupsOfUserSession = $this->groupManager->getUserGroups($userSession); 32 | $groupnamesOfUserSession = array_map(fn ($group) => $group->getGID(), $groupsOfUserSession); 33 | 34 | if (!empty($excludedGroups)) { 35 | $usersNotExclude = array_filter($users, function ($user) use ($excludedGroups, $groupnamesOfUserSession) { 36 | $groups = $this->groupManager->getUserGroups($user); 37 | $groupnames = array_values(array_map(fn ($group) => $group->getGID(), $groups)); 38 | $commonGroups = array_intersect($groupnamesOfUserSession, $groupnames); 39 | return count(array_diff($commonGroups, $excludedGroups)) !== 0; 40 | }); 41 | } 42 | 43 | return $usersNotExclude; 44 | } 45 | } 46 | 47 | /** 48 | * @param IUser[] $users 49 | * 50 | * @return IUser[] 51 | */ 52 | public function filterUsersGroupOnly(array $users): array { 53 | $usersInTheSameGroup = []; 54 | $userSession = $this->userSession->getUser(); 55 | $groupsOfUserSession = $this->groupManager->getUserGroups($userSession); 56 | 57 | foreach ($groupsOfUserSession as $group) { 58 | $usersInTheSameGroup = array_merge($usersInTheSameGroup, $group->getUsers()); 59 | } 60 | 61 | $usersInTheSameGroup = array_filter( 62 | $users, 63 | function ($user) use ($usersInTheSameGroup) { 64 | $usernames = array_values(array_map(fn ($user) => $user->getUID(), $usersInTheSameGroup)); 65 | return in_array($user->getUID(), $usernames); 66 | }); 67 | 68 | return $usersInTheSameGroup; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /lib/Upgrade/Upgrade.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Upgrade; 26 | 27 | class Upgrade { 28 | public const CONTROL_MIGRATION_V3 = 'controlMigrationV3'; 29 | } 30 | -------------------------------------------------------------------------------- /lib/Upgrade/UpgradeFixV300V301.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Upgrade; 26 | 27 | use OCA\Workspace\Db\GroupFoldersGroupsMapper; 28 | use OCA\Workspace\Db\SpaceMapper; 29 | use OCP\AppFramework\Services\IAppConfig; 30 | use OCP\IGroupManager; 31 | 32 | class UpgradeFixV300V301 extends UpgradeV300 { 33 | public function __construct( 34 | private GroupFoldersGroupsMapper $groupfoldersGroupsMapper, 35 | private IAppConfig $appConfig, 36 | private IGroupManager $groupManager, 37 | private SpaceMapper $spaceMapper, 38 | ) { 39 | parent::__construct( 40 | $groupfoldersGroupsMapper, 41 | $appConfig, 42 | $groupManager, 43 | $spaceMapper 44 | ); 45 | } 46 | 47 | public function upgrade(): void { 48 | parent::changePrefixForWorkspaceManagerGroups(); 49 | parent::changePrefixForWorkspaceUserGroups(); 50 | $this->changeConventionForSubgroups(); 51 | $this->appConfig->setAppValue(Upgrade::CONTROL_MIGRATION_V3, '1'); 52 | } 53 | 54 | protected function changeConventionForSubgroups(): void { 55 | $subgroups = $this->groupfoldersGroupsMapper->getSpacenamesGroupIds(); 56 | $subgroups = array_filter($subgroups, function ($subgroup) { 57 | return !str_starts_with($subgroup['group_id'], 'SPACE-G'); 58 | }); 59 | foreach ($subgroups as $subgroup) { 60 | $group = $this->groupManager->get($subgroup['group_id']); 61 | if (is_null($group)) { 62 | throw new \Exception('Group not found for the migration of workspace to version 3.0.0'); 63 | } 64 | $oldSubgroup = $subgroup['group_id']; 65 | $subgroupExploded = explode('-', $oldSubgroup); 66 | $subgroupSliced = array_slice($subgroupExploded, 0, -1); 67 | $groupname = implode('-', $subgroupSliced); 68 | $groupname = 'G-' . $groupname . '-' . $subgroup['space_name']; 69 | $group->setDisplayName($groupname); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/Upgrade/UpgradeInterface.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\Upgrade; 26 | 27 | interface UpgradeInterface { 28 | public function upgrade(): void; 29 | } 30 | -------------------------------------------------------------------------------- /lib/User/UserFinder.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\User; 26 | 27 | use OCP\IUser; 28 | use OCP\IUserManager; 29 | 30 | class UserFinder { 31 | public function __construct( 32 | private IUserManager $userManager, 33 | ) { 34 | } 35 | 36 | /** 37 | * @param string $email 38 | */ 39 | public function findByEmail(string $email): ?IUser { 40 | $users = $this->userManager->getByEmail($email); 41 | return $users[0]; 42 | } 43 | 44 | /** 45 | * @param string $uid 46 | */ 47 | public function findByUID(string $uid): ?IUser { 48 | $user = $this->userManager->get($uid); 49 | return $user; 50 | } 51 | 52 | /** 53 | * @param string $pattern 54 | */ 55 | public function findUser(string $pattern): ?IUser { 56 | $REGEX_FULL_MAIL = '/^[a-zA-Z0-9_.+-].+@[a-zA-Z0-9_.+-]/'; 57 | 58 | if (preg_match($REGEX_FULL_MAIL, $pattern) === 1) { 59 | $user = $this->findByEmail($pattern); 60 | } else { 61 | $user = $this->findByUID($pattern); 62 | } 63 | 64 | return $user; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/User/UserPresenceChecker.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\User; 26 | 27 | use OCP\IUserManager; 28 | 29 | class UserPresenceChecker { 30 | public function __construct( 31 | private IUserManager $userManager, 32 | private UserFinder $userFinder, 33 | ) { 34 | } 35 | 36 | public function checkUserExist(string $pattern): bool { 37 | $user = $this->userFinder->findUser($pattern); 38 | if (is_null($user)) { 39 | return false; 40 | } 41 | return true; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/User/UserSearcher.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * @license GNU AGPL version 3 or any later version 9 | * 10 | * This program is free software: you can redistribute it and/or modify 11 | * it under the terms of the GNU Affero General Public License as 12 | * published by the Free Software Foundation, either version 3 of the 13 | * License, or (at your option) any later version. 14 | * 15 | * This program is distributed in the hope that it will be useful, 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | * GNU Affero General Public License for more details. 19 | * 20 | * You should have received a copy of the GNU Affero General Public License 21 | * along with this program. If not, see . 22 | * 23 | */ 24 | 25 | namespace OCA\Workspace\User; 26 | 27 | use OCP\IUser; 28 | use OCP\IUserManager; 29 | 30 | class UserSearcher { 31 | public function __construct( 32 | private IUserManager $userManager, 33 | ) { 34 | } 35 | 36 | /** 37 | * @param string $email 38 | * @return IUser[] 39 | */ 40 | public function searchUsersByMailing(string $email): array { 41 | return $this->userManager->getByEmail($email); 42 | } 43 | 44 | /** 45 | * @param string $displayname 46 | * @return IUser[] 47 | */ 48 | public function searchUsersByDisplayName(string $displayname): array { 49 | $users = []; 50 | 51 | $displayname = $displayname === '*' ? '' : $displayname; 52 | $users = $this->userManager->searchDisplayName($displayname, 50); 53 | 54 | $users = array_unique($users, SORT_REGULAR); 55 | 56 | return $users; 57 | } 58 | 59 | /** 60 | * @param string $pattern 61 | * @return IUser[] 62 | */ 63 | public function searchUsers(string $pattern): array { 64 | $users = []; 65 | $REGEX_FULL_MAIL = '/^[a-zA-Z0-9_.+-].+@[a-zA-Z0-9_.+-]/'; 66 | 67 | if (preg_match($REGEX_FULL_MAIL, $pattern) === 1) { 68 | $users = $this->searchUsersByMailing($pattern); 69 | } else { 70 | $users = $this->searchUsersByDisplayName($pattern); 71 | } 72 | 73 | /** 74 | * Change OC\User\LazyUser to OC\User\User. 75 | */ 76 | $users = array_map(fn ($user) => $this->userManager->get($user->getUID()), $users); 77 | 78 | return $users; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lib/Users/Formatter/UserImportedFormatter.php: -------------------------------------------------------------------------------- 1 | groupManager->getUserGroups($user) as $group) { 32 | if (in_array($group->getGID(), array_keys($space['groups']))) { 33 | array_push($groups, $group->getGID()); 34 | } 35 | } 36 | 37 | $spaceUserGid = UserGroup::get($space['id']); 38 | 39 | return [ 40 | 'uid' => $user->getUID(), 41 | 'name' => $user->getDisplayName(), 42 | 'email' => $user->getEmailAddress(), 43 | 'subtitle' => $user->getEmailAddress(), 44 | 'groups' => $groups, 45 | 'is_connected' => !$this->connectedGroupsService->isStrictSpaceUser($user->getUID(), $spaceUserGid), 46 | 'profile' => $this->urlGenerator->linkToRouteAbsolute('core.ProfilePage.index', ['targetUserId' => $user->getUID()]), 47 | 'role' => $role 48 | ]; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /lib/Users/UsersExistCheck.php: -------------------------------------------------------------------------------- 1 | userManager->userExists($user); 24 | if (!$userNotExist) { 25 | return false; 26 | } 27 | } 28 | 29 | return true; 30 | } 31 | 32 | /** 33 | * Check if an user exist or not. 34 | */ 35 | public function checkUserExist(string $name): bool { 36 | return $this->userManager->userExists($name); 37 | } 38 | 39 | public function checkUserExistByEmail(string $email): bool { 40 | $userEmail = $this->userManager->getByEmail($email); 41 | 42 | if (count($userEmail) > 1) { 43 | $message = $this->translate->t( 44 | 'The %s email address is duplicated in your instance.' 45 | . ' Impossible to know which users choice or maybe is' 46 | . ' an error.', 47 | $email 48 | ); 49 | throw new EmailDoesntUniqueException( 50 | 'Email address doesn\'t unique', 51 | $message 52 | ); 53 | } 54 | 55 | if (!$userEmail) { 56 | return false; 57 | } 58 | 59 | return true; 60 | } 61 | 62 | public function checkUsersExistByEmail(array $emails): bool { 63 | 64 | foreach ($emails as $email) { 65 | $userEmail = $this->userManager->getByEmail($email); 66 | 67 | if (count($userEmail) > 1) { 68 | $message = $this->translate->t( 69 | 'The %s email address is duplicated in your instance.' 70 | . ' Impossible to know which users choice or maybe is' 71 | . ' an error.', 72 | $email 73 | ); 74 | throw new EmailDoesntUniqueException( 75 | 'Email address doesn\'t unique', 76 | $message 77 | ); 78 | } 79 | 80 | if (!$userEmail) { 81 | return false; 82 | } 83 | } 84 | 85 | return true; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lib/Workspace/WorkspaceChecker.php: -------------------------------------------------------------------------------- 1 | workspaceCheckService->isExist($data['workspace_name'])) { 19 | $workspacesAreNotExist[] = $data['workspace_name']; 20 | } 21 | } 22 | 23 | if (!empty($workspacesAreNotExist)) { 24 | $workspacesAreNotExist = array_map(fn ($spacename) => " - $spacename\n", $workspacesAreNotExist); 25 | $message .= "The Workspace names below already exist:\n" . implode('', $workspacesAreNotExist); 26 | $message .= "\n"; 27 | 28 | return $message; 29 | } 30 | 31 | return null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /phpunit.integration.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ./tests/Integration 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ./tests/Unit 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /screenshots/Workspace-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-1.png -------------------------------------------------------------------------------- /screenshots/Workspace-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-10.png -------------------------------------------------------------------------------- /screenshots/Workspace-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-2.png -------------------------------------------------------------------------------- /screenshots/Workspace-3-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-3-2.png -------------------------------------------------------------------------------- /screenshots/Workspace-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-4.png -------------------------------------------------------------------------------- /screenshots/Workspace-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-5.png -------------------------------------------------------------------------------- /screenshots/Workspace-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-6.png -------------------------------------------------------------------------------- /screenshots/Workspace-7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-7.png -------------------------------------------------------------------------------- /screenshots/Workspace-8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-8.png -------------------------------------------------------------------------------- /screenshots/Workspace-9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arawa/workspace/0389af32fc53cff30d81687b6ba895996ad00594/screenshots/Workspace-9.png -------------------------------------------------------------------------------- /src/AlertRemoveGroup.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 58 | 59 | 72 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 26 | 27 | 41 | -------------------------------------------------------------------------------- /src/Error403.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 38 | 39 | 57 | 58 | 85 | -------------------------------------------------------------------------------- /src/Errors/BadCreateError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class BadCreateError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'BadCreateError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/BadGetError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class BadGetError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'BadGetError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/Groupfolders/AddGroupToGroupfolderError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class AddGroupToGroupfolderError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'AddGroupToGroupfolderError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/Groupfolders/AddGroupToManageACLForGroupfolderError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class AddGroupToManageACLForGroupfolderError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'AddGroupToManageACLForGroupfolderError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/Groupfolders/BadCreateError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class CreateGroupfolderError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'CreateGroupfolderError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/Groupfolders/CheckGroupfolderNameError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class CheckGroupfolderNameExistError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'CheckGroupfolderNameExistError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/Groupfolders/EnableAclGroupfolderError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class EnableAclGroupfolderError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'EnableAclGroupfolderError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/Groupfolders/GetGroupfolderError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class GetGroupfolderError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'GetGroupfolderError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/Errors/Groupfolders/RemoveGroupToManageACLForGroupfolderError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | export default class RemoveGroupToManageACLForGroupfolderError extends Error { 24 | 25 | constructor(message) { 26 | super(message) 27 | this.name = 'RemoveGroupToManageACLForGroupfolderError' 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/GroupMenuItem.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 48 | 49 | 51 | -------------------------------------------------------------------------------- /src/Home.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 29 | 30 | 51 | -------------------------------------------------------------------------------- /src/LoadingUsers.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /src/MenuItemSelector.vue: -------------------------------------------------------------------------------- 1 | 21 | 28 | 29 | 61 | 62 | 87 | -------------------------------------------------------------------------------- /src/RemoveSpace.vue: -------------------------------------------------------------------------------- 1 | 22 | 45 | 46 | 77 | 111 | -------------------------------------------------------------------------------- /src/UserCard.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 50 | 51 | 85 | 86 | 128 | -------------------------------------------------------------------------------- /src/constants.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 2021 Baptiste Fotia 5 | * author 2021 Cyrille Bollu 6 | * 7 | * license GNU AGPL version 3 or any later version 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | const ESPACE_MANAGERS = 'GE-' 25 | const ESPACE_USERS = 'U-' 26 | const ESPACE_GID = 'SPACE-' 27 | const ESPACE_GROUP = 'G-' 28 | export const PREFIX_USER = ESPACE_GID + ESPACE_USERS 29 | export const PREFIX_MANAGER = ESPACE_GID + ESPACE_MANAGERS 30 | export const PREFIX_GID_SUBGROUP_SPACE = ESPACE_GID + ESPACE_GROUP 31 | export const PREFIX_DISPLAYNAME_SUBGROUP_SPACE = ESPACE_GROUP 32 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright Copyright (c) 2017 Arawa 3 | * 4 | * @author 2021 Baptiste Fotia 5 | * @author 2021 Cyrille Bollu 6 | * 7 | * @license AGPL-3.0-or-later 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | import Vue from 'vue' 25 | import router from './router.js' 26 | import { linkTo } from '@nextcloud/router' 27 | import store from './store/index.js' 28 | import App from './App.vue' 29 | import { translate as t, translatePlural as n } from '@nextcloud/l10n' 30 | import { Tooltip } from '@nextcloud/vue' 31 | import VueLazyComponent from '@xunlei/vue-lazy-component' 32 | 33 | Vue.mixin({ 34 | methods: { 35 | t, 36 | n, 37 | }, 38 | }) 39 | 40 | // eslint-disable-next-line 41 | __webpack_public_path__ = linkTo('workspace', 'js/') 42 | 43 | Vue.directive('tooltip', Tooltip) 44 | Vue.use(VueLazyComponent) 45 | 46 | export default new Vue({ 47 | el: '#content', 48 | data: { 49 | isUserGeneralAdmin: false, 50 | spaces: {}, 51 | }, 52 | router, 53 | store, 54 | render: (h) => h(App), 55 | }) 56 | -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright Copyright (c) 2017 Arawa 3 | * 4 | * @author 2021 Baptiste Fotia 5 | * @author 2021 Cyrille Bollu 6 | * 7 | * @license AGPL-3.0-or-later 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | import Vue from 'vue' 25 | import Router from 'vue-router' 26 | import { generateUrl } from '@nextcloud/router' 27 | import GroupDetails from './GroupDetails.vue' 28 | import Home from './Home.vue' 29 | import SpaceDetails from './SpaceDetails.vue' 30 | import SpaceTable from './SpaceTable.vue' 31 | import Error403 from './Error403.vue' 32 | 33 | Vue.use(Router) 34 | 35 | export default new Router({ 36 | mode: 'history', 37 | base: generateUrl('/apps/workspace/'), 38 | linkActiveClass: 'active', 39 | routes: [ 40 | { 41 | path: '/', 42 | component: resolve => resolve(Home), 43 | children: [ 44 | { 45 | path: '', 46 | component: SpaceTable, 47 | }, 48 | { 49 | path: 'workspace/:space', 50 | component: SpaceDetails, 51 | }, 52 | { 53 | path: 'group/:space/:slug', 54 | component: GroupDetails, 55 | }, 56 | { 57 | path: 'unauthorized', 58 | component: Error403, 59 | }, 60 | ], 61 | }, 62 | ], 63 | }) 64 | -------------------------------------------------------------------------------- /src/services/Groups/ManagerGroup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 2023 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | import { PREFIX_MANAGER } from '../../constants.js' 24 | 25 | /** 26 | * @param {object} space present the space entity 27 | * @return {string} 28 | */ 29 | function getGid(space) { 30 | const groups = Object.keys(space.groups) 31 | 32 | const spaceGeneralGroupRegex = new RegExp('^' + PREFIX_MANAGER + '[0-9]*$') 33 | 34 | const groupFound = groups.find(function(group) { 35 | if (spaceGeneralGroupRegex.test(group)) { 36 | return true 37 | } 38 | 39 | return false 40 | }) 41 | 42 | return groupFound 43 | } 44 | 45 | const ManagerGroup = { 46 | getGid, 47 | } 48 | 49 | export default ManagerGroup 50 | -------------------------------------------------------------------------------- /src/services/Groups/UserGroup.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 2023 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | import { PREFIX_USER } from '../../constants.js' 24 | 25 | /** 26 | * @param {object} space 27 | * @return {string} 28 | */ 29 | function getGid(space) { 30 | const groups = Object.keys(space.groups) 31 | 32 | const uGroupRegex = new RegExp('^' + PREFIX_USER + '[0-9]*$') 33 | 34 | const groupFound = groups.find(group => { 35 | if (uGroupRegex.test(group)) { 36 | return true 37 | } 38 | 39 | return false 40 | }) 41 | 42 | return groupFound 43 | } 44 | 45 | const UserGroup = { 46 | getGid, 47 | } 48 | 49 | export default UserGroup 50 | -------------------------------------------------------------------------------- /src/services/Notifications/NotificationError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * copyright Copyright (c) 2017 Arawa 3 | * 4 | * author 202é1 Baptiste Fotia 5 | * 6 | * license GNU AGPL version 3 or any later version 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | import { showError } from '@nextcloud/dialogs' 24 | 25 | /** 26 | * 27 | * @param {string} title error notification title 28 | * @param {string} text error notification text 29 | * @param {number | undefined} duration in milliseconds, 7 seconds by default, -1 for permanent notification 30 | * @param {Array | undefined} argsMessage in milliseconds, 7 seconds by default, -1 for permanent notification 31 | */ 32 | export default function showNotificationError(title, text, duration = undefined, argsMessage = undefined) { 33 | title = t('workspace', title) 34 | 35 | text = t('workspace', text) 36 | if (argsMessage) { 37 | text = t('workspace', text, { args: argsMessage[0] }) 38 | } 39 | 40 | const message = `

${title}

${text}

` 41 | const options = duration ? { isHTML: true, timeout: duration } : { isHTML: true } 42 | showError(message, options) 43 | } 44 | -------------------------------------------------------------------------------- /src/store/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright Copyright (c) 2017 Arawa 3 | * 4 | * @author 2021 Baptiste Fotia 5 | * @author 2021 Cyrille Bollu 6 | * 7 | * @license AGPL-3.0-or-later 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | import Vue from 'vue' 25 | import Vuex, { Store } from 'vuex' 26 | import actions from './actions.js' 27 | import { getters } from './getters.js' 28 | import mutations from './mutations.js' 29 | 30 | Vue.use(Vuex) 31 | Vue.config.devtools = true // Debug mode 32 | 33 | const store = new Store({ 34 | state: { 35 | loading: true, 36 | noUsers: false, 37 | loadingUsersWaiting: false, 38 | spaces: {}, 39 | groupfolders: {}, 40 | countWorkspaces: 0, 41 | }, 42 | mutations, 43 | actions, 44 | getters, 45 | }) 46 | 47 | export default store 48 | -------------------------------------------------------------------------------- /src/tests/OC.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright Copyright (c) 2021 Louis Chemineau 3 | * 4 | * @author Louis Chemineau 5 | * 6 | * @license AGPL-3.0-or-later 7 | * 8 | * This program is free software: you can redistribute it and/or modify 9 | * it under the terms of the GNU Affero General Public License as 10 | * published by the Free Software Foundation, either version 3 of the 11 | * License, or (at your option) any later version. 12 | * 13 | * This program is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | * GNU Affero General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Affero General Public License 19 | * along with this program. If not, see . 20 | * 21 | */ 22 | 23 | global.OC = { 24 | L10N: { 25 | translate() { 26 | return '' 27 | }, 28 | }, 29 | 30 | getLanguage() { 31 | return 'en-GB' 32 | }, 33 | 34 | getLocale() { 35 | return 'en_GB' 36 | }, 37 | 38 | isUserAdmin() { 39 | return true 40 | }, 41 | 42 | Util: { 43 | naturalSortCompare(a, b) { 44 | return 0 45 | }, 46 | }, 47 | 48 | config: { 49 | modRewriteWorking: true, 50 | }, 51 | } 52 | -------------------------------------------------------------------------------- /src/tests/__mocks__/axios.js: -------------------------------------------------------------------------------- 1 | import mockAxios from 'jest-mock-axios' 2 | export default mockAxios 3 | -------------------------------------------------------------------------------- /src/tests/__mocks__/styleMock.js: -------------------------------------------------------------------------------- 1 | module.exports = {} 2 | -------------------------------------------------------------------------------- /src/tests/jest.setup.js: -------------------------------------------------------------------------------- 1 | import 'core-js/stable/index.js' 2 | /* eslint-disable-next-line */ 3 | import 'regenerator-runtime/runtime.js' 4 | /* eslint-disable-next-line */ 5 | import { OC } from './OC.js' 6 | import { config } from '@vue/test-utils' 7 | import mockAxios from 'jest-mock-axios' 8 | 9 | document.title = 'Standard Nextcloud title' 10 | 11 | // Mock nextcloud translate functions 12 | config.mocks.$t = function(app, string) { 13 | return string 14 | } 15 | 16 | config.mocks.t = config.mocks.$t 17 | global.t = config.mocks.$t 18 | 19 | config.mocks.$n = function(app, singular, plural, count) { 20 | return singular 21 | } 22 | config.mocks.n = config.mocks.$n 23 | global.n = config.mocks.$n 24 | 25 | global.console = { 26 | ...console, 27 | error: jest.fn(), 28 | debug: jest.fn(), 29 | } 30 | 31 | global.appName = 'workspace' 32 | 33 | global.OCA = {} 34 | 35 | jest.mock('@nextcloud/axios', () => mockAxios) 36 | -------------------------------------------------------------------------------- /stylelint.config.js: -------------------------------------------------------------------------------- 1 | const stylelintConfig = require('@nextcloud/stylelint-config') 2 | 3 | module.exports = stylelintConfig 4 | -------------------------------------------------------------------------------- /templates/index.php: -------------------------------------------------------------------------------- 1 | 22 | 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /tests/Integration/AppTest.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Tests\Integration\Controller; 27 | 28 | use OCP\AppFramework\App; 29 | use Test\TestCase; 30 | 31 | /** 32 | * This test shows how to make a small Integration Test. Query your class 33 | * directly from the container, only pass in mocks if needed and run your tests 34 | * against the database 35 | */ 36 | class AppTest extends TestCase { 37 | private $container; 38 | 39 | public function setUp(): void { 40 | parent::setUp(); 41 | $app = new App('workspace'); 42 | $this->container = $app->getContainer(); 43 | } 44 | 45 | public function testAppInstalled(): void { 46 | $appManager = $this->container->query('OCP\App\IAppManager'); 47 | $this->assertTrue($appManager->isInstalled('workspace')); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /tests/Unit/Controller/PageControllerTest.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | namespace OCA\Workspace\Tests\Unit\Controller; 27 | 28 | use OCA\Workspace\Controller\PageController; 29 | 30 | use OCA\Workspace\Service\UserService; 31 | use OCP\AppFramework\Http\TemplateResponse; 32 | use OCP\IConfig; 33 | use PHPUnit\Framework\MockObject\MockObject; 34 | use PHPUnit\Framework\TestCase; 35 | 36 | class PageControllerTest extends TestCase { 37 | private $controller; 38 | private $userId = 'john'; 39 | private MockObject&UserService $userService; 40 | private MockObject&IConfig $config; 41 | 42 | public function setUp(): void { 43 | $this->userService = $this->createMock(UserService::class); 44 | $this->config = $this->createMock(IConfig::class); 45 | 46 | $this->controller = new PageController( 47 | $this->userService, 48 | $this->config, 49 | ); 50 | } 51 | 52 | public function testIndex(): void { 53 | $result = $this->controller->index(); 54 | 55 | $this->assertEquals('index', $result->getTemplateName()); 56 | $this->assertTrue($result instanceof TemplateResponse); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | 7 | * @author 2021 Cyrille Bollu 8 | * 9 | * @license GNU AGPL version 3 or any later version 10 | * 11 | * This program is free software: you can redistribute it and/or modify 12 | * it under the terms of the GNU Affero General Public License as 13 | * published by the Free Software Foundation, either version 3 of the 14 | * License, or (at your option) any later version. 15 | * 16 | * This program is distributed in the hope that it will be useful, 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | * GNU Affero General Public License for more details. 20 | * 21 | * You should have received a copy of the GNU Affero General Public License 22 | * along with this program. If not, see . 23 | * 24 | */ 25 | 26 | if (!defined('PHPUNIT_RUN')) { 27 | define('PHPUNIT_RUN', 1); 28 | } 29 | 30 | require_once __DIR__ . '/../../../lib/base.php'; 31 | 32 | // Fix for "Autoload path not allowed: .../tests/lib/testcase.php" 33 | \OC::$loader->addValidRoot(OC::$SERVERROOT . '/tests'); 34 | 35 | // Fix for "Autoload path not allowed: .../workspace/tests/testcase.php" 36 | \OC_App::loadApp('workspace'); 37 | 38 | OC_Hook::clear(); 39 | -------------------------------------------------------------------------------- /tests/phpunit.unit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Unit 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright Copyright (c) 2017 Arawa 3 | * 4 | * @author 2021 Baptiste Fotia 5 | * @author 2021 Cyrille Bollu 6 | * 7 | * @license AGPL-3.0-or-later 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | const webpackConfig = require('@nextcloud/webpack-vue-config') 25 | 26 | module.exports = webpackConfig 27 | -------------------------------------------------------------------------------- /webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @copyright Copyright (c) 2017 Arawa 3 | * 4 | * @author 2021 Baptiste Fotia 5 | * @author 2021 Cyrille Bollu 6 | * 7 | * @license AGPL-3.0-or-later 8 | * 9 | * This program is free software: you can redistribute it and/or modify 10 | * it under the terms of the GNU Affero General Public License as 11 | * published by the Free Software Foundation, either version 3 of the 12 | * License, or (at your option) any later version. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU Affero General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU Affero General Public License 20 | * along with this program. If not, see . 21 | * 22 | */ 23 | 24 | const { merge } = require('webpack-merge') 25 | const webpackConfig = require('@nextcloud/webpack-vue-config') 26 | 27 | module.exports = merge(webpackConfig, { 28 | devtool: 'source-map' 29 | }) 30 | --------------------------------------------------------------------------------