1. 23 Oct, 2015 2 commits
  2. 22 Oct, 2015 1 commit
    • Jörg Richter's avatar
      Config module: rename "Configure" command (#830). · c4c57a5b
      Jörg Richter authored
      ... to "Show Configuration" as this is what the submenu items acutually do: they just *show*/*reveal* the respective config topic. *Configure* would only be the proper term if the user //has permission// to *edit* the config topic.
      
      See #830.
      c4c57a5b
  3. 21 Oct, 2015 1 commit
  4. 20 Oct, 2015 1 commit
  5. 19 Oct, 2015 2 commits
    • Jörg Richter's avatar
      Core Access Control: get private workspace (#816). · 8722b61d
      Jörg Richter authored
      Core Access Control API:
      
      1 new method:
      {{{
      Topic getPrivateWorkspace(String username);
      }}}
      Returns the private workspace of the given user.
      
      This is a privileged method, it bypasses the access control system.
      
      Note: a user can have more than one private workspace. The workspace returned
      by this method is the one that holds the user's password topic.
      
      Example:
      {{{
      Topic workspace = dms.getAccessControl().getPrivateWorkspace("admin");
      }}}
      
      See #816.
      8722b61d
    • Jörg Richter's avatar
      Extend Core Access Control: email address (#816). · 62be7cf8
      Jörg Richter authored
      Core Access Control API:
      
      1 new method:
      {{{
      boolean emailAddressExists(String emailAddress);
      }}}
      Returns true if an "Email Address" (dm4.contacts.email_address) topic with the given value exists,
      false otherwise.
      This is a privileged method, it runs as "System".
      
      Example:
      {{{
      boolean exists = dms.getAccessControl().emailAddressExists("i@me.com");
      }}}
      
      See #816.
      62be7cf8
  6. 15 Oct, 2015 1 commit
  7. 14 Oct, 2015 2 commits
    • Jörg Richter's avatar
      New config property: "dm4.webservice.path" (#448). · 71e30b94
      Jörg Richter authored
      Only these 2 values are supported:
      {{{
        /     For use with Apache Felix HTTP (the default)
        /*    For use with OPS4J Pax Web
      }}}
      
      This way a distribution assembler may choose between Felix HTTP and Pax Web without branching/compiling.
      
      See #448.
      71e30b94
    • Jörg Richter's avatar
      Introduce server-side preInstall() hook (#843). · 98342194
      Jörg Richter authored
      The preInstall() hook is triggered //before// the plugin is installed in the database.
      The preInstall() hook is triggered each time the plugin starts, just like the init() hook.
      
      The preInstall() hook is useful in particular in conjunction with the new Config service (#830).
      
      CHANGES
      
      Slight change in init() hook: the init() hook is triggered //after// the plugin's event listeners and OSGi service are registered, that is at the very end of the plugin activation phase. Thus at init() time the plugin developer can be shure all the plugin aspects are fully functional.
      
      Formerly the init() hook was triggered after installing the plugin in the database but //before// registering the event listeners and OSGi service.
      
      Overview of the plugin activation phase:
      1. invoke preInstall() hook
      2. install plugin in the database
         (includes creating plugin topic, running migrations, fire type introduction events)
      3. register event listeners
      4. register OSGi service
      5. invoke init() hook
      
      See #843.
      98342194
  8. 13 Oct, 2015 3 commits
    • Jörg Richter's avatar
      Admins can enable/disable user accounts (#842). · 80ccd1b1
      Jörg Richter authored
      Admins can enable/disable user accounts interactively by right-clicking a Username topic and then "Configure -> Login enabled" and then "Edit".
      (Alternatively to "Configure -> Login enabled" the "Login enabled" config topic can be revealed directly through the detail panel).
      
      New configuration property in config file:
      {{{
      dm4.security.new_accounts_are_enabled=true
      }}}
      If true newly created user accounts are enabled instantly. This is the default.
      If false user accounts must be manually enabled by an administrator (using the Webclient).
      
      See #842.
      80ccd1b1
    • Jörg Richter's avatar
      Add migrations to create config topics (#830). · e0abaf2e
      Jörg Richter authored
      Equip the Access Control and Files plugins with migrations to create default config topics ("Login enabled", "Disk Quota") for existing user accounts when UPDATING a DM installation.
      
      See #830.
      e0abaf2e
    • Jörg Richter's avatar
      Config service: refactor ConfigDefinition (#830). · abfadc5d
      Jörg Richter authored
      Enum `ConfigTarget` replaces the 2 `ConfigDefinition` subclasses.
      The `ConfigDefinition` constructor has changed accordingly.
      
      See #830.
      abfadc5d
  9. 12 Oct, 2015 1 commit
  10. 11 Oct, 2015 1 commit
    • Jörg Richter's avatar
      Drop lazy config topic creation (#830). · 062d9afc
      Jörg Richter authored
      Now the Config module attaches all config topics to every newly created topic immediately.
      
      CHANGES
      
      Config API:
      
      1 new method:
      {{{
      createConfigTopic(String configTypeUri, Topic topic)
      }}}
      To be used in migrations to attach a config topic to existing topics.
      
      See #830.
      062d9afc
  11. 09 Oct, 2015 1 commit
  12. 07 Oct, 2015 1 commit
    • Jörg Richter's avatar
      Webclient: revise searchmode extension API (#839). · 921d0346
      Jörg Richter authored
      Providing a search mode implementation is slightly more convenient for the plugin developer. She must no longer handle events but implements all the searchmode in a concise constructor function. Furthermore she can rely on a higher-level API and must not interact with the toolbar DOM.
      
      BREAKING CHANGES
      
      1 method dropped:
      {{{
      dm4c.do_search(searchmode)
      }}}
      Use `dm4c.toolbar.do_search()` instead (see below).
      
      2 client-side events dropped:
      {{{
      search
      searchmode_widget
      }}}
      
      A searchmode implementation is added to the Webclient's toolbar by calling `dm4c.toolbar.add_searchmode()`. You pass 2 parameters: an URI to identify your searchmode and a constructor function which contains all aspectes a searchmode is made of, that is 1) the label to display in the searchmode menu, 2) the searchmode widget, and 3) the actual search operation.
      
      Example:
      {{{
      dm4c.toolbar.add_searchmode(MY_SEARCHMODE_URI, function() {
      
          this.label = "My searchmode label"
      
          this.widget = function() {
              ... build my widget
              return my_searchmode_widget
          }
      
          this.search = function() {
              ... doing my search
              return my_searchresult_topic
          }
      })
      }}}
      You see you're no longer required to interact with the toolbar DOM, e.g. adding your searchmode to the menu. And you must no longer register event listeners and check if the event is directed to your very searchmode.
      
      You can place the `add_searchmode()` call directly into your plugin's constructor function.
      
      To select a searchmode by default (when the Webclient starts) your plugin can use a "init[x]" handler and call:
      {{{
      dm4c.toolbar.select_searchmode(MY_SEARCHMODE_URI)
      }}}
      Note: the `dm4c.toolbar.select_searchmode()` method exists like before but is no a high-level call. You must no longer care about manually choosing the searchmode from the searchmode menu.
      
      == Overview of the new searchmode API (5 methods) ==
      
      Adds a searchmode to the searchmode menu
      {{{
      dm4c.toolbar.add_searchmode(searchmode_uri, constructor_func)
      }}}
      
      Selects a searchmode programmatically
      {{{
      dm4c.toolbar.select_searchmode(searchmode_uri)
      }}}
      
      Returns the URI of the selected searchmode
      {{{
      dm4c.toolbar.get_searchmode_uri()
      }}}
      
      Triggers the current search programmatically
      {{{
      dm4c.toolbar.do_search()
      }}}
      
      Enables/disables the toolbar's search button
      {{{
      dm4c.toolbar.enable_search_button(state)
      }}}
      
      For a detailed description see the API comments in:
      https://github.com/jri/deepamehta/blob/master/modules/dm4-webclient/src/main/resources/web/script/gui/toolbar_panel.js
      
      For example implementations see the "By Text" and "By Type" searchmodes:
      https://github.com/jri/deepamehta/blob/master/modules/dm4-webclient/src/main/resources/web/script/internal_plugins/fulltext_plugin.js
      https://github.com/jri/deepamehta/blob/master/modules/dm4-typesearch/src/main/resources/web/script/plugin.js
      
      See #839.
      921d0346
  13. 05 Oct, 2015 3 commits
    • Jörg Richter's avatar
      Remove "service" packages (#836). · 8ff4c295
      Jörg Richter authored
      Adapt standard plugins to convention: a plugin's service interface resides in the plugin's main package.
      
      See #836.
      8ff4c295
    • Jörg Richter's avatar
      Drop @ProvidesService annotation (#836). · 477f3f3c
      Jörg Richter authored
      Sorry, change of plan: the @ProvidesService annotation is dropped after all.
      
      BREAKING CHANGE
      
      New rule for recognizing which service interface a plugin implements: among the interfaces implemented by a plugin the service interface is the one whose name ends with "Service". No annotation is needed. This is more "Convention over Configuration" like.
      
      The service interface can be located anywhere (even in another module), but the convention is for it to reside in the plugin's main package. The package "service" has no special meaning anymore, and, according to the convention, is not used anymore.
      
      See #836.
      477f3f3c
    • Jörg Richter's avatar
      Make WebPublishingService internal to Core (#834). · b47f9486
      Jörg Richter authored
      The `dm4-webpublishing` module is dropped after all.
      
      The WebPublishingService is now a internal Core facility (as originally requested in #408).
      It is deliberately not consumable as an OSGi service.
      
      Plugin developers still import all standard event listeners from `de.deepamehta.core.service.event`.
      
      See #834.
      See #408.
      b47f9486
  14. 04 Oct, 2015 1 commit
    • Jörg Richter's avatar
      New @ProvidesService annotation (#836). · c61913d0
      Jörg Richter authored
      A plugin can implement an OSGi service which is specified in other module.
      This allow for more complex use cases.
      
      BREAKING CHANGES
      
      A service interface must no longer extend `PluginService`.
      The `PluginService` interface is obsolete and dropped.
      
      Furthermore a service interface must no longer be located in the plugin's `service` package.
      It can be located at arbitrary locations, even in other modules.
      
      To tell DM which service a plugin provides its main class is now to be annotated with `@ProvidesService`.
      The annotation argument is the service interface (a `Class` object).
      
      Example:
      {{{
      import de.deepamehta.core.service.ProvidesService;
      
      import de.deepamehta.plugins.config.ConfigService;
      
      @ProvidesService(ConfigService.class)
      public class ConfigPlugin extends PluginActivator implements ConfigService {
          ...
      }
      }}}
      
      See #836.
      c61913d0
  15. 03 Oct, 2015 3 commits
  16. 02 Oct, 2015 3 commits
    • Jörg Richter's avatar
      Revise web publishing wording (#834). · 69b303cf
      Jörg Richter authored
      "Static Resources" comprise "Web Resources" and "File System Resources".
      
      Web Resources (as found in a bundle's /web directory) are no longer referred to as Static Resources.
      
      "Static Resources" is only used when
      - referring to Bundle resources which are not web resources
      - meaning the generic sense as mentioned above
      
      See #834.
      69b303cf
    • Jörg Richter's avatar
      Merge branch 'felix-http' · 6306aeb7
      Jörg Richter authored
      6306aeb7
    • Jörg Richter's avatar
      Separate WebPublishingService from Core (#834). · e849dfd6
      Jörg Richter authored
      New module:
      {{{
      dm4-webpublishing
      }}}
      
      BREAKING CHANGES
      
      7 listeners are moved from `de.deepamehta.core.service.event` to `de.deepamehta.webpublishing.listeners`:
      {{{
      de.deepamehta.webpublishing.listeners.PreSendAssociationListener
      de.deepamehta.webpublishing.listeners.PreSendAssociationTypeListener
      de.deepamehta.webpublishing.listeners.PreSendTopicListener
      de.deepamehta.webpublishing.listeners.PreSendTopicTypeListener
      de.deepamehta.webpublishing.listeners.ResourceRequestFilterListener
      de.deepamehta.webpublishing.listeners.ServiceRequestFilterListener
      de.deepamehta.webpublishing.listeners.ServiceResponseFilterListener
      }}}
      
      See #834.
      e849dfd6
  17. 30 Sep, 2015 1 commit
  18. 28 Sep, 2015 1 commit
    • Jörg Richter's avatar
      Failed uploads are reported to the user (#815). · e505bd86
      Jörg Richter authored
      If an error occurs while a file upload the error is reported to the user by the means of a dialog box.
      
      CHANGES
      
      Client-side `dm4c` API:
      
      1 new method:
      {{{
      dm4c.open_error_dialog(server_response)
      }}}
      
      Opens an error dialog and renders a server response.
      
      The server response will be rendered as
      1) either arbitrary error text or as a chain of exceptions, and
      2) the server status.
      
      A chain of exceptions is rendered if the server response meets these conditions: "content_type" is
      "application/json" and "content" is the JSON representation of a Java exception (as occurred at server-side):
      an object with "exception", "message", and "cause" properties. The "cause" value is again an exception object.
      The final exception has no "cause" property.
      {{
      @param   server_response  The server response to render. An object with 4 properties:
                   content_type -- media type of the error content (string)
                   content      -- the error content (string)
                   status_code  -- the server status code (number)
                   status_text  -- the server status text (string)
      }}}
      
      See #815.
      e505bd86
  19. 27 Sep, 2015 2 commits
    • Jörg Richter's avatar
      Fix cross-workspace file repo browsing (#815). · d71435d5
      Jörg Richter authored
      File and Folder topics are always assigned to the workspace the file repo actually belongs to. When a File or Folder topic is created (while browsing) the currently selected workspace is not relevant.
      
      Thus collaborative cross-workspace file repo browsing is now supported.
      
      Consider the situation when a user browses a public file repo from within hers private workspace (by revealing existing Folder topics), and then another user browses the same files.
      
      When per-workspace file repos are switched off (the default) the entire file repo belongs to the public "DeepaMehta" workspace.
      
      CHANGES
      
      `de.deepamehta.core.service.accesscontrol.AccessControl` API:
      
      2 new methods:
      {{{
      Topic getWorkspace(String uri)
      
      long getDeepaMehtaWorkspaceId()
      }}}
      
      See #815.
      d71435d5
    • Jörg Richter's avatar
      Core: fix workspace suppression (#752). · 4fe13ed2
      Jörg Richter authored
      See #752.
      4fe13ed2
  20. 26 Sep, 2015 1 commit
    • Jörg Richter's avatar
      Fix: browse public file repos by anonymous (#573). · 2f8e0d44
      Jörg Richter authored
      Anonymous can //reveal// public Folder topics and browse its contained files/folders.
      
      Note: anonymous still can't //create// new file browsers as the Create menu is not available at all (except in Common workspaces, provided the `write_requires_login` flag is set to `false`). I regard this OK at the moment.
      
      See #573.
      2f8e0d44
  21. 25 Sep, 2015 2 commits
    • Jörg Richter's avatar
      Files: fix directory listing serialization (#832). · 66d0dd76
      Jörg Richter authored
      Files module REST API:
      {{{
      GET /files/{path}
      }}}
      The returned file items include size and media type information.
      By mistake these were not included in older DM versions.
      
      BREAKING CHANGE
      
      `de.deepamehta.core.util.DeepaMehtaUtils` API:
      
      1 method renamed:
      {{{
      objectsToJSON() -> toJSONArray()
      }}}
      
      1 method dropped:
      {{{
      stringsToJson()
      }}}
      Use `new JSONArray(...)` instead.
      
      See #832.
      66d0dd76
    • Jörg Richter's avatar
      Change dm4.filerepo.path default value (#832). · 0ae9d6ab
      Jörg Richter authored
      The default value for the `dm4.filerepo.path` config property is `/` instead of empty.
      Empty is no longer a valid value for that config property.
      `/` regards the entire file system as the DM file repo (as formerly specified by empty).
      
      See #832.
      0ae9d6ab
  22. 23 Sep, 2015 2 commits
    • Jörg Richter's avatar
      Adapt plugins to new workspace suppression (#752). · 0582ce1a
      Jörg Richter authored
      See #752.
      0582ce1a
    • Jörg Richter's avatar
      Redesign workspace assignment suppression (#752). · ea0834b0
      Jörg Richter authored
      BREAKING CHANGES
      
      As a user of a REST API you must no longer care about adding the `no_workspace_assignment` query parameter to your request. The `no_workspace_assignment` query parameter has no function anymore. It is obsolete.
      
      As a developer of a service you explicitly control which code blocks must execute without the standard workspace assignments. You do so by calling `runWithoutWorkspaceAssignment()` (part of Core's access control support).
      
      Example:
      {{{
      try {
          Topic result = dms.getAccessControl().runWithoutWorkspaceAssignment(new Callable<Topic>() {
              @Override
              public Topic call() {
                  // All topics/associations created here will get no workspace assignment.
                  //
                  // You could do workspace assignment manually (either by using the Workspaces
                  // service or by `dms.getAccessControl().assignToWorkspace()`).
                  //
                  return aTopic;
              }
          });
      } catch (Exception e) {
          throw new RuntimeException("Operation failed", e);
      }
      }}}
      
      You pass your code block as a `java.util.concurrent.Callable`. The standard workspace assignment for all topics/associations created within that code block is suppressed then.
      
      Your Callable can return a result object. That object will be finally returned by `runWithoutWorkspaceAssignment()`. The type parameter of the Callable is the type of the result object.
      
      The `runWithoutWorkspaceAssignment()` method throws `Exception`, so you must catch or declare it.
      
      `runWithoutWorkspaceAssignment()` calls can be nested. So you can safely call all 3rd-party API's from within the Callable.
      
      See #752.
      ea0834b0
  23. 22 Sep, 2015 1 commit
    • Jörg Richter's avatar
      Config plugin: support ADMIN role (#830, #812). · f0c7de48
      Jörg Richter authored
      Config modification role ADMIN is now supported: Config topics defined with that role can only be modified by admins.
      
      The remaining config modification roles (CREATOR, OWNER, MEMBER) are not yet supported.
      
      Files plugin: the individual (per-user) disk quota can be modified by admins only.
      
      See #830.
      See #812.
      f0c7de48
  24. 14 Sep, 2015 2 commits
    • Jörg Richter's avatar
      Plugin shutdown() hook error handling (#831). · a456b300
      Jörg Richter authored
      If an error occurs in a plugin's shutdown() hook the error is logged and stopping the plugin proceeds.
      
      See #831.
      a456b300
    • Jörg Richter's avatar
      Enforce per-user disk quota config (#812). · 4a073962
      Jörg Richter authored
      The individual (per-user) disk quota as configured by a Username topic's "Configure -> Disk Quota" command is now enforced.
      
      CHANGES
      
      Core API:
      
      1 new method in AccessControl:
      {{{
      Topic getUsernameTopic(HttpServletRequest request)
      }}}
      Convenience method that returns the Username topic that corresponds to a request.
      Basically it calls `getUsernameTopic(getUsername(request))`.
      
      1 new static method in CoreActivator:
      {{{
      <S> S getService(Class<S> clazz)
      }}}
      Returns a registered OSGi service.
      
      See #812.
      4a073962
  25. 13 Sep, 2015 1 commit
    • Jörg Richter's avatar
      Rename global disk quota config property (#812). · 9b61e120
      Jörg Richter authored
      1 config property renamed:
      {{{
      dm4.filerepo.user_quota -> dm4.filerepo.disk_quota
      }}}
      Standard disk quota (for file uploads) allocated to each user (in MB).
      
      Individual (per-user) disk quotas can be configured by the Username topic's "Configure -> Disk Quota" command.
      
      See #812.
      9b61e120