Coder Social home page Coder Social logo

expath-ml-console's People

Contributors

fgeorges avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

expath-ml-console's Issues

Support for groups

Preliminary work on supporting groups.

At the end of the day, find a mechanism to install the same package on all app servers in a group (as convenience, because it is not possible to install a package at the group level itself: http://markmail.org/message/zyym6s5b4ya5svru).

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ git status
# On branch feature/bootstrap
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   src/appserver.xq
#   modified:   src/plumbing/rewriter.xml
#   modified:   src/repo.xq
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   src/appserver/repo-page.xql
#   src/group.xq
no changes added to commit (use "git add" and/or "git commit -a")

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ cat src/group.xq 
xquery version "3.0";

import module namespace p = "http://expath.org/ns/ml/console/repo-page" at "appserver/repo-page.xql";
import module namespace a = "http://expath.org/ns/ml/console/admin"     at "lib/admin.xql";
import module namespace t = "http://expath.org/ns/ml/console/tools"     at "lib/tools.xql";
import module namespace v = "http://expath.org/ns/ml/console/view"      at "lib/view.xql";

declare default element namespace "http://www.w3.org/1999/xhtml";

declare namespace pp = "http://expath.org/ns/repo/packages";

(: path relative to the AS. TODO: To be moved to a lib... :)
declare variable $packages-path := 'expath-repo/.expath-pkg/packages.xml';

(:~
 : The overall page function.
 :)
declare function local:page()
   as element()+
{
   let $id-str := t:mandatory-field('id')
   let $id     := xs:unsignedLong($id-str)
   let $group  := a:get-group($id)
(:   let $pkgs   := a:appserver-get-packages($group) :)
   return
(:      if ( fn:empty($pkgs) ) then :)
         p:when-no-repo('group', $group/a:name, $group/@id)
(:      else
         p:page-with-repo('group', $group/a:name, $group/@id, $pkgs) :)
};

v:console-page('../', 'pkg', 'Group', local:page#0)

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ cat src/appserver/repo-page.xql 
xquery version "3.0";

module namespace p = "http://expath.org/ns/ml/console/repo-page";

import module namespace a = "http://expath.org/ns/ml/console/admin" at "../lib/admin.xql";
import module namespace t = "http://expath.org/ns/ml/console/tools" at "../lib/tools.xql";
import module namespace v = "http://expath.org/ns/ml/console/view"  at "../lib/view.xql";

declare default element namespace "http://www.w3.org/1999/xhtml";

declare namespace pp = "http://expath.org/ns/repo/packages";

(: path relative to the AS :)
declare variable $packages-path := 'expath-repo/.expath-pkg/packages.xml';

(:~
 : Implement the page when there is no repo setup fot the app server or group.
 :)
declare function p:when-no-repo($kind as xs:string, $name as xs:string, $id as xs:string)
   as element()+
{
   <wrapper>
      <p>The { $kind } "<code>{ $name }</code>" has no repo setup.  In order to be
         able to install packages for this { $kind }, you must first setup a repo.</p>
      <p>Do you want to set one up?</p>
      <form method="post" action="{ $id }/init-repo" enctype="multipart/form-data">
         <button class="btn btn-default" type="submit">Initialize</button>
      </form>
   </wrapper>/*
};

(:~
 : Implement the page when there is a repo setup fot the app server or group.
 :)
declare function p:page-with-repo(
   $kind as xs:string,
   $name as xs:string,
   $id   as xs:string,
   $pkgs as element(pp:packages)
) as element()+
{
   <wrapper>
      <p>Packages on the { $kind } "<code>{ $name }</code>".</p>
      <h3>Installed packages</h3>
      {
         if ( fn:empty($pkgs/pp:package) ) then
            <p>There is no package installed on this app server.</p>
         else
            p:package-table($pkgs, $id)
      }
      <h3>Install from file</h3>
      <p>Install packages and applications from your filesystem, using a package
         file (usually a *.xar file).</p>
      {
         v:form($id || '/install-pkg', (
            v:input-file('xar', 'Package file'),
            v:submit('Install')
            (: v:input-checkbox('override', 'true', 'Override the package if it already exists') :) ))
      }
      <h3>Install from CXAN</h3>
      <p>Install packages and applications directly from CXAN, using a package
         name or a CXAN ID (one or the other), and optionally a version number
         (retrieve the latest version by default).</p>
      <p>The default CXAN website is <a href="http://cxan.org/">http://cxan.org/</a>.
         If you are not sure, keep that one.  If you want to use the development
         CXAN website, you can use <a href="http://dev.cxan.org/">http://devcxan.org/</a>
         instead.</p>
      {
         (: TODO: Next step: use an XSLT stylesheet, and generate XML instead of
            calling functions to generate HTML... :)
         v:form($id || '/install-cxan', (
            v:input-text('pkg',     'ID',      'CXAN package ID...'),
            v:input-text('name',    'Name',    '...or package name'),
            v:input-text('version', 'Version', 'Package version (latest by default)'),
            v:submit('Install'),
            v:input-select('std-website', 'Source website', (
               v:input-option('prod', 'http://cxan.org/'),
               v:input-option('dev',  'http://dev.cxan.org/'))),
            v:input-text('other=website', 'Other source',
               'Other specific CXAN website to use')))
      }
      <h3>Nuke the repo</h3>
      <p>Delete the package repository that has been setup on this app server.</p>
      {
         v:form($id || '/delete-repo', v:submit('Delete'))
      }
   </wrapper>/*
};

(:~
 : Build the package table for one app server or group.
 :
 : @param $pkg The packages element.
 : @param $id The ID of the app server or group.
 :)
declare %private function p:package-table($pkgs as element(pp:packages), $id as xs:string)
   as element(table)
{
   <table class="table table-striped">
      <thead>
         <th>Name</th>
         <th>Dir</th>
         <th>Version</th>
         <th>Action</th>
      </thead>
      <tbody> {
         for $p in $pkgs/pp:package
         order by $p/fn:string(@dir)
         return
            p:package-row($p, $id)
      }
      </tbody>
   </table>
};

(:~
 : Build one row in the package table.
 :
 : @param $pkg One package element.
 : @param $id The ID of the app server or group.
 :)
declare %private function p:package-row($pkg as element(pp:package), $id as xs:string)
   as element(tr)
{
   <tr>
      <td>{ $pkg/fn:string(@name) }</td>
      <td>{ $pkg/fn:string(@dir) }</td>
      <td>{ $pkg/fn:string(@version) }</td>
      <td> {
         v:inline-form($id || '/pkg/' || $pkg/fn:escape-html-uri(@dir) || '/delete',
            v:submit('Delete'))
      }
      </td>
   </tr>
};

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/scp:[email protected]:/home/fgeorges/ml-console $ git diff
diff --git a/src/appserver.xq b/src/appserver.xq
index 71c190f..c0671a2 100644
--- a/src/appserver.xq
+++ b/src/appserver.xq
@@ -1,8 +1,9 @@
 xquery version "3.0";

-import module namespace a = "http://expath.org/ns/ml/console/admin" at "lib/admin.xql";
-import module namespace t = "http://expath.org/ns/ml/console/tools" at "lib/tools.xql";
-import module namespace v = "http://expath.org/ns/ml/console/view"  at "lib/view.xql";
+import module namespace p = "http://expath.org/ns/ml/console/repo-page" at "appserver/repo-page.xql";
+import module namespace a = "http://expath.org/ns/ml/console/admin"     at "lib/admin.xql";
+import module namespace t = "http://expath.org/ns/ml/console/tools"     at "lib/tools.xql";
+import module namespace v = "http://expath.org/ns/ml/console/view"      at "lib/view.xql";

 declare default element namespace "http://www.w3.org/1999/xhtml";

@@ -12,92 +13,6 @@ declare namespace pp = "http://expath.org/ns/repo/packages";
 declare variable $packages-path := 'expath-repo/.expath-pkg/packages.xml';

 (:~
- : Implement the page when there is no repo setup fot the app server.
- :)
-declare function local:page-no-repo($as as element(a:appserver))
-   as element()+
-{
-   <wrapper>
-      <p>The app server "<code>{ $as/a:name }</code>" has no repo setup.  In
-         order to be able to install packages for this app server, you must
-         first setup a repo.  Do you want to set one up?</p>
-      <form method="post" action="{ $as/@id }/init-repo" enctype="multipart/form-data">
-         <input type="submit" value="Initialize"/>
-         <span> repo for this app server.</span>
-      </form>
-   </wrapper>/*
-};
-
-(:~
- : Implement the page when there is a repo setup fot the app server.
- :)
-declare function local:page-with-repo($as as element(a:appserver), $pkgs as element(pp:packages))
-   as element()+
-{
-   <wrapper>
-      <p>Packages on the app server "<code>{ $as/a:name }</code>".</p>
-      <h3>Installed packages</h3>
-      {
-         if ( fn:empty($pkgs/pp:package) ) then
-            <p>There is no package installed on this app server.</p>
-         else (
-            <table class="table table-striped">
-               <thead>
-                  <th>Name</th>
-                  <th>Dir</th>
-                  <th>Version</th>
-                  <th>Action</th>
-               </thead>
-               <tbody> {
-                  for $p in $pkgs/pp:package
-                  order by $p/fn:string(@dir)
-                  return
-                     local:package-row($p, $as)
-               }
-               </tbody>
-            </table>
-         )
-      }
-      <h3>Install from file</h3>
-      <p>Install packages and applications from your filesystem, using a package
-         file (usually a *.xar file).</p>
-      {
-         v:form($as/@id || '/install-pkg', (
-            v:input-file('xar', 'Package file'),
-            v:submit('Install')
-            (: v:input-checkbox('override', 'true', 'Override the package if it already exists') :) ))
-      }
-      <h3>Install from CXAN</h3>
-      <p>Install packages and applications directly from CXAN, using a package
-         name or a CXAN ID (one or the other), and optionally a version number
-         (retrieve the latest version by default).</p>
-      <p>The default CXAN website is <a href="http://cxan.org/">http://cxan.org/</a>.
-         If you are not sure, keep that one.  If you want to use the development
-         CXAN website, you can use <a href="http://dev.cxan.org/">http://devcxan.org/</a>
-         instead.</p>
-      {
-         (: TODO: Next step: use an XSLT stylesheet, and generate XML instead of
-            calling functions to generate HTML... :)
-         v:form($as/@id || '/install-cxan', (
-            v:input-text('pkg',     'ID',      'CXAN package ID...'),
-            v:input-text('name',    'Name',    '...or package name'),
-            v:input-text('version', 'Version', 'Package version (latest by default)'),
-            v:submit('Install'),
-            v:input-select('std-website', 'Source website', (
-               v:input-option('prod', 'http://cxan.org/'),
-               v:input-option('dev',  'http://dev.cxan.org/'))),
-            v:input-text('other=website', 'Other source',
-               'Other specific CXAN website to use')))
-      }
-      <h3>Nuke the repo</h3>
-      <p>Delete the package repository that has been setup on this app server.</p>
-      {
-         v:form($as/@id || '/delete-repo', v:submit('Delete'))
-      }
-   </wrapper>/*
-};
-
-(:~
  : The overall page function.
  :)
 declare function local:page()
@@ -109,24 +24,9 @@ declare function local:page()
    let $pkgs   := a:appserver-get-packages($as)
    return
       if ( fn:empty($pkgs) ) then
-         local:page-no-repo($as)
+         p:when-no-repo('app server', $as/a:name, $as/@id)
       else
-         local:page-with-repo($as, $pkgs)
-};
-
-declare function local:package-row($pkg as element(pp:package), $as as element(a:appserver))
-   as element(tr)
-{
-   <tr>
-      <td>{ $pkg/fn:string(@name) }</td>
-      <td>{ $pkg/fn:string(@dir) }</td>
-      <td>{ $pkg/fn:string(@version) }</td>
-      <td> {
-         v:inline-form($as/@id || '/pkg/' || $pkg/fn:escape-html-uri(@dir) || '/delete',
-            v:submit('Delete'))
-      }
-      </td>
-   </tr>
+         p:page-with-repo('app server', $as/a:name, $as/@id, $pkgs)
 };

 v:console-page('../', 'pkg', 'App server', local:page#0)
diff --git a/src/plumbing/rewriter.xml b/src/plumbing/rewriter.xml
index 159d813..51655cf 100644
--- a/src/plumbing/rewriter.xml
+++ b/src/plumbing/rewriter.xml
@@ -27,6 +27,14 @@
       <add-query-param name="pkg">$2</add-query-param>
       <dispatch>/appserver/delete-pkg.xq</dispatch>
    </match-path>
+   <match-path matches="^/group/([0-9]+)$">
+      <add-query-param name="id">$1</add-query-param>
+      <dispatch>/group.xq</dispatch>
+   </match-path>
+   <match-path matches="^/group/([0-9]+)/init-repo$">
+      <add-query-param name="id">$1</add-query-param>
+      <dispatch>/group/init-repo.xq</dispatch>
+   </match-path>
    <match-path matches="^/db/([0-9]+)/browse$">
       <add-query-param name="id">$1</add-query-param>
       <dispatch>/database/browse.xq</dispatch>
diff --git a/src/repo.xq b/src/repo.xq
index 44df246..016fe69 100644
--- a/src/repo.xq
+++ b/src/repo.xq
@@ -9,28 +9,32 @@ declare function local:page()
    as element()+
 {
    let $groups := a:get-groups()/a:group
-   let $count := fn:count($groups)
+   let $count  := fn:count($groups)
    return
-      <wrapper>
-         {
-            if ( $count eq 0 ) then
-               <p>There is no group in this MarkLogic instance.  A bug, surely...</p>
-            else if ( $count eq 1 ) then (
-               <p>There is one single group in this MarkLogic instance:
-                  <code>{ $groups[1]/xs:string(a:name) }</code>.</p>,
+      <wrapper> {
+         if ( $count eq 0 ) then (
+            <p>There is no group in this MarkLogic instance.  A bug, surely...</p>
+         )
+         else if ( $count eq 1 ) then (
+            <p>There is one single group in this MarkLogic instance:
+               <code>{ $groups/xs:string(a:name) }</code>.</p>,
+            <p>Go to the <a href="group/{ $groups/xs:string(@id) }">group page</a>
+               to install packages at the group level itself.</p>,
+            <p>The app servers in the group are:</p>,
+            local:appservers-table($groups)
+         )
+         else (
+            <p>There are { $count } groups in this MarkLogic instance.</p>,
+            for $g in $groups
+            return (
+               <h4>Group <code>{ $g/a:name }</code></h4>,
+               <p>Go to the <a href="group/{ $g/xs:string(@id) }">group page</a>
+                  to install packages at the group level itself.</p>,
                <p>The app servers in the group are:</p>,
-               local:appservers-table($groups)
+               local:appservers-table($g)
             )
-            else (
-               <p>There are { $count } groups in this MarkLogic instance.</p>,
-               for $g in $groups
-               return (
-                  <h4>Group <code>{ $g/a:name }</code></h4>,
-                  <p>The app servers in the group are:</p>,
-                  local:appservers-table($g)
-               )
-            )
-         }
+         )
+      }
       </wrapper>/*
 };

Initialization of a fresh installation fails

I tried to install the console on my new Developer licensed ML server:

  1. git clone https://github.com/fgeorges/expath-ml-console.git
  2. cd expath-ml-console
  3. I edited credentials in xproject/mlenvs/dev.sjon
  4. npm install mlproj -g
  5. mlproj -e dev setup

After pressing the button at http://localhost:8010/init there is a:
500 Internal Server Error

JS-JAVASCRIPT: xdmp.dir(resp); -- Error running JavaScript request: TypeError: xdmp.dir is not a function
in /init/do-init.sjs, at 19:13, in get() [javascript]
in /init/do-init.sjs, at 128:16 [javascript]
in /init/do-init.sjs [javascript]

I am on a 18GB memory running Windows Server 2012 R2 Datacenter
with MarkLogic Server 9.0-8.2 amd64 (normally I would use Linux)

Edit collections on a document

When displaying a document in the Browser, the collections it is part of are displayed, in a bullet-list kind of way.

It would be handy to be able to add the document to existing collections, as well as to new collections. And to remove it from collections it is part of.

Suggested by Mijneer Peter Kester.

Updating a document's content in the browser clobbers its permissions

Steps to reproduce:

  1. insert an XML document to the database (outside of expath, if necessary), add at least 1 permission
  2. navigate to the document's location using expath (logged in as ML admin)
  3. edit the document content and save it using the built-in editor
  4. any permissions added in the first step are missing.

I would expect the permissions to be unchanged, but it looks like they're getting clobbered by the admin's default permissions (which are none).

Tested on current master branch, safari, ml 9.0-1.1. Observed earlier on ml8 as well.

Gather security-related information for a module

Add some tools in order to gather some security-related information about a module. Of course, this is a sharp tool one would have to use carefully, but it would be a convenient way to investigate some issue (or at least to provide someone with some context about it).

Here is some pseudo-code (pseudo because there are some calls which should be done against different databases and they are not resolved properly, but the idea is there), some pseudo-code to retrieve the names (and the IDs) of the roles associated to a module. Add the relevant databases IDs and names as well to the "report" (the user should be able to chose between XML and HTML):

import module namespace sec="http://marklogic.com/xdmp/security"
   at "/MarkLogic/security.xqy";

declare variable $modules-db-name := 'SCS-modules';
declare variable $module-uri      := '/app/controllers/appbuilder.xqy';

declare function local:get-permissions($uri as xs:string, $db-name as xs:string) as element(sec:permission)*
{
   (: TODO: To be executed against database $db-name :)
   xdmp:document-get-permissions($uri)
};

(: TODO: Instead of returning a bunch of strings, return structured info in an element. :)
(: TODO: Also, pass all role IDs at once, and get all the relevant info from one call
   against the security database. :)
declare function local:get-roles-names($perms as element(sec:permission)*)
{
   for $p in $perms
   return
      (: TODO: To be executed against the security database of database $db-name :)
      $p/sec:get-role-names(sec:role-id)
};

(: TODO: Return pairs of ID/name instead. :)
declare function local:get-module-roles($uri as xs:string, $db-name as xs:string)
{
   local:get-roles-names(
     local:get-permissions($uri, $db-name))
};

local:get-module-roles($module-uri, $modules-db-name)

Hard-coded username/password in do-init.sjs

Do you have any plans or guidance for passing the database password to the get(url) function in do-init.sjs? We would like to upgrade our console installations, but we will not be able to hard code the username and password in that function because they vary between systems.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.