diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5fdb100ae..db8260084 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,7 +52,7 @@ jobs: - name: Use Node.js uses: actions/setup-node@v1 with: - node-version: '18.17.0' + node-version: '20.14.0' # Npm global packages caching - name: Cache global npm modules diff --git a/VERSION b/VERSION index e61ecd12d..37c2d9960 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -5.3.5 +5.4 diff --git a/bin/watch-assets.sh b/bin/watch-assets.sh new file mode 100755 index 000000000..977924112 --- /dev/null +++ b/bin/watch-assets.sh @@ -0,0 +1,26 @@ +#!/bin/bash + +filename="frontend/dist/assets/frontend.js" + +watchFile() { + local filename="$1" + local m1=$(md5sum "$filename") + + while true; do + sleep 10 + local m2=$(md5sum "$filename") + echo "" + echo "$m1" + echo "$m2" + if [ "$m1" != "$m2" ] ; then + m1=$m2 + rm -f public/frontend-index-test.html + cp -rf frontend/dist/* public/ + cp public/{index,frontend-index-test}.html + cp public/{index,frontend-index-development}.html + echo "Refreshed frontend" + fi + done +} + +watchFile "$filename" \ No newline at end of file diff --git a/config/docker/development/Ember.dockerfile b/config/docker/development/Ember.dockerfile index 2eef34396..eb3011666 100644 --- a/config/docker/development/Ember.dockerfile +++ b/config/docker/development/Ember.dockerfile @@ -1,4 +1,4 @@ -FROM danlynn/ember-cli:5.2.1-node_18.17 +FROM danlynn/ember-cli:5.9.0 RUN chown 1000:1000 /myapp diff --git a/db/migrate/002_group_and_team_changes.rb b/db/migrate/002_group_and_team_changes.rb index d988573aa..39aa66fda 100644 --- a/db/migrate/002_group_and_team_changes.rb +++ b/db/migrate/002_group_and_team_changes.rb @@ -14,11 +14,11 @@ def up rename_column :teams, :groupname, :name add_column :teams, :visible, :boolean, default: true, null: false add_column :teams, :private, :boolean, default: false, null: false - Team.find_each do |team| - teammember = Teammember.first(conditions: ["user_id = ? and team_id = ?", team.user_id, team.id]) - teammember.team_admin = true - teammember.save - end + #Team.find_each do |team| + #teammember = Teammember.first(conditions: ["user_id = ? and team_id = ?", team.user_id, team.id]) + #teammember.team_admin = true + #teammember.save + #end remove_column :teams, :user_id # Add the new admin flag to the users table @@ -33,19 +33,19 @@ def up end # create a default group for every team with accounts - Team.find_each do |team| - group = Group.new() - group.name = "Default" - group.description = "Default group, created for migration" - group.team_id = team.id - group.save + #Team.find_each do |team| + #group = Group.new() + #group.name = "Default" + #group.description = "Default group, created for migration" + #group.team_id = team.id + #group.save - # Accounts are now linked to their groups and not directly to the team - Account.where("group_id = ?", team.id).find_each do |account| - account.group_id = group.id - account.save - end - end + ## Accounts are now linked to their groups and not directly to the team + #Account.where("group_id = ?", team.id).find_each do |account| + #account.group_id = group.id + #account.save + #end + #end end @@ -81,4 +81,4 @@ def down remove_column :grouppasswords, :team_admin end -end \ No newline at end of file +end diff --git a/db/migrate/004_add_no_root_flag_to_teams.rb b/db/migrate/004_add_no_root_flag_to_teams.rb index c62109838..ee7889652 100644 --- a/db/migrate/004_add_no_root_flag_to_teams.rb +++ b/db/migrate/004_add_no_root_flag_to_teams.rb @@ -9,10 +9,10 @@ class AddNoRootFlagToTeams < ActiveRecord::Migration[4.2] def change add_column :teams, :noroot, :boolean, default: 0, null: false - Team.reset_column_information - Team.find_each do |team| - team.noroot = false - team.save - end + #Team.reset_column_information + #Team.find_each do |team| + #team.noroot = false + #team.save + #end end end diff --git a/db/migrate/20190604054153_sqlite_boolean_values.rb b/db/migrate/20190604054153_sqlite_boolean_values.rb index b399aa529..858f4d4b3 100644 --- a/db/migrate/20190604054153_sqlite_boolean_values.rb +++ b/db/migrate/20190604054153_sqlite_boolean_values.rb @@ -5,14 +5,14 @@ class SqliteBooleanValues < ActiveRecord::Migration[5.2] def up return unless sqlite? - User.where("locked = 't'").update_all(locked: 1) - User.where("locked = 'f'").update_all(locked: 0) + #User.where("locked = 't'").update_all(locked: 1) + #User.where("locked = 'f'").update_all(locked: 0) - Team.where("visible = 't'").update_all(visible: 1) - Team.where("visible = 'f'").update_all(visible: 0) + #Team.where("visible = 't'").update_all(visible: 1) + #Team.where("visible = 'f'").update_all(visible: 0) - Team.where("private = 't'").update_all(private: 1) - Team.where("private = 'f'").update_all(private: 0) + #Team.where("private = 't'").update_all(private: 1) + #Team.where("private = 'f'").update_all(private: 0) end private diff --git a/db/schema.rb b/db/schema.rb index 40e3c98f2..53367d69c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,9 +10,9 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2022_07_19_120958) do +ActiveRecord::Schema[7.1].define(version: 2022_07_19_120958) do create_table "encryptables", force: :cascade do |t| - t.string "name", limit: 255, default: "", null: false + t.string "name", limit: 255 t.integer "folder_id" t.text "description" t.datetime "created_at", precision: nil, null: false diff --git a/frontend/.eslintrc.js b/frontend/.eslintrc.js index f9c373015..e1ebf1917 100644 --- a/frontend/.eslintrc.js +++ b/frontend/.eslintrc.js @@ -1,12 +1,10 @@ module.exports = { root: true, - parser: "babel-eslint", + parser: "@babel/eslint-parser", parserOptions: { - ecmaVersion: 2018, + ecmaVersion: 2023, sourceType: "module", - ecmaFeatures: { - legacyDecorators: true - } + requireConfigFile: false }, plugins: ["ember"], extends: [ diff --git a/frontend/.npmcheckrc b/frontend/.npmcheckrc new file mode 100644 index 000000000..8cbfc529e --- /dev/null +++ b/frontend/.npmcheckrc @@ -0,0 +1,54 @@ +{ + "depcheck": { + "ignoreMatches": [ + "frontend", + "tracked-built-ins", + "sass", + "loader.js", + + "eslint-plugin-ember", + "eslint-plugin-prettier", + "eslint-plugin-ember", + + "@ember/optional-features", + "webpack", + "bootstrap", + "text-security", + "minimist", + "@babel/runtime", + + "@ember/application", + "@ember/service", + "@ember/utils", + "@ember/routing", + "@ember/array", + "@ember/object", + "@ember/component", + "@ember/controller", + + "ember-toggle", + "ember-moment", + "ember-in-viewport", + "ember-file-upload", + "ember-fetch", + "ember-cli-terser", + "ember-basic-dropdown", + "ember-cli-sass", + "ember-cli-app-version", + "ember-auto-import", + "ember-cli-app-version", + "ember-auto-import", + "ember-power-select-with-create", + "ember-cli-string-helpers", + "ember-cli-moment-shim", + "ember-cli-inject-live-reload", + "ember-bootstrap-power-select", + "ember-cli-babel", + + "@ember-data/serializer", + "@ember-data/model", + "@ember-data/adapter", + "ember-inflector" + ] + } +} diff --git a/frontend/app/adapters/application.js b/frontend/app/adapters/application.js index c0d4ae61c..4afb431a9 100644 --- a/frontend/app/adapters/application.js +++ b/frontend/app/adapters/application.js @@ -1,22 +1,19 @@ import JSONAPIAdapter from "@ember-data/adapter/json-api"; -import { computed } from "@ember/object"; import { pluralize } from "ember-inflector"; import { underscore } from "@ember/string"; import ENV from "../config/environment"; -export default JSONAPIAdapter.extend({ - namespace: "api", +export default class ApplicationAdapter extends JSONAPIAdapter { + namespace = "api"; pathForType(type) { return pluralize(underscore(type)); - }, + } - headers: computed(function () { - /* eslint-disable no-undef */ + get headers() { return { "X-CSRF-Token": ENV.CSRFToken, "content-type": "application/json" }; - /* eslint-enable no-undef */ - }) -}); + } +} diff --git a/frontend/app/adapters/encryptable-credential.js b/frontend/app/adapters/encryptable-credential.js index 6cf40d7be..0945e8e0f 100644 --- a/frontend/app/adapters/encryptable-credential.js +++ b/frontend/app/adapters/encryptable-credential.js @@ -1,7 +1,7 @@ import ApplicationAdapter from "./application"; -export default ApplicationAdapter.extend({ +export default class EncryptableCredentialAdapter extends ApplicationAdapter{ pathForType() { return "encryptables"; } -}); +}; diff --git a/frontend/app/adapters/encryptable-file.js b/frontend/app/adapters/encryptable-file.js index 6cf40d7be..c0ba6e01a 100644 --- a/frontend/app/adapters/encryptable-file.js +++ b/frontend/app/adapters/encryptable-file.js @@ -1,7 +1,7 @@ import ApplicationAdapter from "./application"; -export default ApplicationAdapter.extend({ +export default class EncryptableFileAdapter extends ApplicationAdapter{ pathForType() { return "encryptables"; } -}); +}; diff --git a/frontend/app/adapters/folder.js b/frontend/app/adapters/folder.js index b400148f9..b66b100df 100644 --- a/frontend/app/adapters/folder.js +++ b/frontend/app/adapters/folder.js @@ -1,7 +1,7 @@ import ApplicationAdapter from "./application"; -export default ApplicationAdapter.extend({ - namespace: "api/teams", +export default class FolderAdapter extends ApplicationAdapter { + namespace = "api/teams"; urlForQuery(query, modelName) { if (query.teamId) { @@ -11,7 +11,7 @@ export default ApplicationAdapter.extend({ return url; } return super.urlForQuery(query, modelName); - }, + } urlForQueryRecord(query, modelName) { if (query.teamId) { @@ -22,27 +22,27 @@ export default ApplicationAdapter.extend({ return url; } return super.urlForQueryRecord(query, modelName); - }, + } urlForCreateRecord(modelName, snapshot) { return `/${this.namespace}/${snapshot.belongsTo("team", { id: true })}/${this.pathForType()}`; - }, + } urlForUpdateRecord(id, modelName, snapshot) { return `/${this.namespace}/${snapshot.belongsTo("team", { id: true })}/${this.pathForType()}/${id}`; - }, + } urlForDeleteRecord(id, modelName, snapshot) { return `/${this.namespace}/${snapshot.belongsTo("team", { id: true })}/${this.pathForType()}/${id}`; - }, + } - pathForType: function () { + pathForType() { return "folders"; } -}); +} diff --git a/frontend/app/adapters/team-api-user.js b/frontend/app/adapters/team-api-user.js index 351c9ef7b..a0ef56c16 100644 --- a/frontend/app/adapters/team-api-user.js +++ b/frontend/app/adapters/team-api-user.js @@ -1,11 +1,11 @@ import ApplicationAdapter from "./application"; import { pluralize } from "ember-inflector"; -export default ApplicationAdapter.extend({ +export default class TeamApiUserAdapter extends ApplicationAdapter { pathForType(modelName) { let snakeCased = modelName.replace("-", "_"); return pluralize(snakeCased); - }, + } urlForQuery(query, modelName) { let teamId = query.teamId; @@ -15,4 +15,4 @@ export default ApplicationAdapter.extend({ } return super.urlForQuery(query, modelName); } -}); +} diff --git a/frontend/app/adapters/teammember.js b/frontend/app/adapters/teammember.js index ffae131f0..1ee063f26 100644 --- a/frontend/app/adapters/teammember.js +++ b/frontend/app/adapters/teammember.js @@ -1,7 +1,7 @@ import ApplicationAdapter from "./application"; -export default ApplicationAdapter.extend({ - namespace: "api/teams", +export default class TeammemberAdapter extends ApplicationAdapter { + namespace = "api/teams"; urlForQuery(query, modelName) { if (query.teamId) { @@ -18,21 +18,21 @@ export default ApplicationAdapter.extend({ return url; } return super.urlForQuery(query, modelName); - }, + } pathForType() { return "members"; - }, + } urlForCreateRecord(modelName, snapshot) { return `/${this.namespace}/${snapshot.belongsTo("team", { id: true })}/${this.pathForType()}`; - }, + } urlForDeleteRecord(id, modelName, snapshot) { return `/${this.namespace}/${snapshot.belongsTo("team", { id: true })}/${this.pathForType()}/${id}`; } -}); +} diff --git a/frontend/app/components/admin/setting-multiselect-with-create.js b/frontend/app/components/admin/setting-multiselect-with-create.js index 99ff13b3c..1dac540bc 100644 --- a/frontend/app/components/admin/setting-multiselect-with-create.js +++ b/frontend/app/components/admin/setting-multiselect-with-create.js @@ -18,7 +18,7 @@ export default class SettingMultiselectWithCreateComponent extends Component { if (!this.args.selectedOptions) { this.store.findAll(this.args.settingModel).then((settings) => { const setting = settings.firstObject; - if (this.args.options && this.args.options.length) { + if (this.args.options && this.args.options?.length) { this.selectedOptions = this.args.options.filter((option) => { return setting.value.includes(option.value); }); diff --git a/frontend/app/components/admin/user/deletion-form.js b/frontend/app/components/admin/user/deletion-form.js index fd7b2bb03..f65eefb82 100644 --- a/frontend/app/components/admin/user/deletion-form.js +++ b/frontend/app/components/admin/user/deletion-form.js @@ -23,9 +23,11 @@ export default class AdminUserDeletionFormComponent extends Component { this.isDeletionFormShown = !this.isDeletionFormShown; if (this.isDeletionFormShown) { - this.onlyTeammemberTeams = this.store.query("team", { + this.store.query("team", { only_teammember_user_id: this.args.user.id - }); + }).then((result) => { + this.onlyTeammemberTeams = result + }) } } diff --git a/frontend/app/components/encryptable-file/form.js b/frontend/app/components/encryptable-file/form.js index a8eafdc0f..d6a964cea 100644 --- a/frontend/app/components/encryptable-file/form.js +++ b/frontend/app/components/encryptable-file/form.js @@ -44,10 +44,9 @@ export default class Form extends BaseFormComponent { this.changeset.csrfToken = ENV.CSRFToken; } - @action - setDefaults() { - this.presetTeamAndFolder(); - this.changeset.validate(); + setDefaults(element, [thisRef]) { + thisRef.presetTeamAndFolder(thisRef); + thisRef.changeset.validate(); } get availableFolders() { @@ -60,16 +59,16 @@ export default class Form extends BaseFormComponent { : []; } - presetTeamAndFolder() { - let selectedFolder = this.args.folder || this.navService.selectedFolder; + presetTeamAndFolder(thisRef) { + let selectedFolder = thisRef.args.folder || thisRef.navService.selectedFolder; let selectedTeam = - selectedFolder?.get("team") || this.navService.selectedTeam; + selectedFolder?.get("team") || thisRef.navService.selectedTeam; if (!isEmpty(selectedTeam)) { - this.changeset.set("team", selectedTeam); + thisRef.changeset.set("team", selectedTeam); } if (!isEmpty(selectedFolder)) { - this.changeset.set("folder", selectedFolder); + thisRef.changeset.set("folder", selectedFolder); } } @@ -108,6 +107,7 @@ export default class Form extends BaseFormComponent { } return false; } + showSuccessMessage() { let msg = this.intl.t("flashes.encryptable_files.uploaded"); this.notify.success(msg); diff --git a/frontend/app/components/team/index.js b/frontend/app/components/team/index.js index 13592baf0..3248c4aed 100644 --- a/frontend/app/components/team/index.js +++ b/frontend/app/components/team/index.js @@ -4,7 +4,6 @@ import { tracked } from "@glimmer/tracking"; export default class Index extends Component { @service navService; - @service loading; @tracked model = this.args.model; constructor() { diff --git a/frontend/app/controllers/teams/index.js b/frontend/app/controllers/teams/index.js index 1a03fc946..44e5841da 100644 --- a/frontend/app/controllers/teams/index.js +++ b/frontend/app/controllers/teams/index.js @@ -1,6 +1,4 @@ -import { inject as service } from "@ember/service"; import ApplicationController from "../application"; export default class TeamsIndexController extends ApplicationController { - @service loading; } diff --git a/frontend/app/index.html b/frontend/app/index.html index 70130daa0..d99309269 100644 --- a/frontend/app/index.html +++ b/frontend/app/index.html @@ -19,6 +19,9 @@ +
+ + {{content-for "body-footer"}}