Cloudron makes it easy to run web apps like WordPress, Nextcloud, GitLab on your server. Find out more or install now.


Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Bookmarks
  • Search
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo

Cloudron Forum

Apps - Status | Demo | Docs | Install
  1. Cloudron Forum
  2. Discuss
  3. Cloudron API Docu - Set Operators correction?

Cloudron API Docu - Set Operators correction?

Scheduled Pinned Locked Moved Discuss
apidocumentation
4 Posts 2 Posters 432 Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • 32463 Offline
    32463 Offline
    3246
    wrote on last edited by 3246
    #1

    Hi @girish et al, I may read this wrong but when I troubleshot a n8n call to set an operator for an app, the manual says:

    {
      "accessRestriction": {
        "users": [
          "uid-321dsa..."
        ],
        "groups": [
          "gid-321dsa..."
        ]
      }
    }
    

    But when I ran it I kept getting errors until:

    {
      "operators": {
        "users": [
          "uid-321dsa..."
        ]
    }
    }
    

    The manual also says in the main part:
    117d1ae9-ded5-4398-8af2-e6677a33e2c5-image.png

    accessRestriction instead of operators.

    Am I reading it wrong or should it be updated to say operators?

    Ref. https://docs.cloudron.io/api.html#tag/Apps/operation/setAppOperators

    👉 Find our more www.bebraver.online

    1 Reply Last reply
    0
    • jamesJ Offline
      jamesJ Offline
      james
      Staff
      wrote on last edited by james
      #2

      Hello @3246
      The API doc is currently outdated.
      Here is a full curl example for making a user / a group an app operator:

      curl "https://my.$DOMAIN.$TLD/api/v1/apps/$APPID/configure/operators" \
        -H "Authorization: Bearer $APITOKEN" \
        -H 'content-type: application/json' \
        --data-raw '{"operators":{"users":["uid-3eca9898-baca-473c-a988-d127967218c9"],"groups":[]}}'
      

      You can always grab the API paths from the Cloudron dashboard in the browser network inspect when you do the task in the dashboard.
      afdf21b7-5edc-4621-abd9-5c5030d66da2-image.png

      1 Reply Last reply
      1
      • 32463 Offline
        32463 Offline
        3246
        wrote on last edited by
        #3

        Super, thanks James!

        While I have you, can you let me know how to run a cmd in an app via the API. I tried using "Create exec" but not getting anywhere, although it doesn't error (I wish it did, at least I had more to go on!) lol

        👉 Find our more www.bebraver.online

        1 Reply Last reply
        0
        • jamesJ Offline
          jamesJ Offline
          james
          Staff
          wrote on last edited by
          #4

          Hello @3246
          With the cloudron cli you can run e.g:

          cloudron exec --app $APP -- fallocate -l 4M /app/data/4M
          

          See cloudron exec --help:

          Usage: cloudron exec [options] [cmd...]
          
          Exec a command in an application
          
          Options:
            -t,--tty             Allocate tty
            --app <id/location>  App id or location
            -h, --help           display help for command
            Examples:
          
              $ cloudron exec --app myapp          # run an interactive shell
              $ cloudron exec --app myapp ls       # run command
              $ cloudron exec --app myapp -- ls -l # use -- to indicate end of options
          

          Was not sure if possible via the API but since I can debug the cloudron cli and see what it do I figured something out.

          Send the to /api/v1/apps/$APPID/exec
          # Command is an array `ls -lah /app/data` would become for each space ["ls", "-lah", "/app/data/"]
          curl "https://my.$DOMAIN.$TLD/api/v1/apps/$APPID/exec" \
            -H 'Authorization: Bearer $APITOKEN' \
            -H 'content-type: application/json' \
            --data-raw '["ls", "-lah", "/app/data/"]'
          # this returns and id
          {
            "id": "a90bcfcec1d29f7a595638ea66c8ac0bb53b594047ac74fc80bf97f75fed0c19"
          }
          

          But getting the output of the executed command is. . . tricky.
          Just look at the source code for the cli for this part:

              const searchParams = new URLSearchParams({
                  rows: stdout.rows || 24,
                  columns: stdout.columns || 80,
                  access_token: token,
                  tty
              });
          
              const req = https.request({
                  hostname: adminFqdn,
                  path: `/api/v1/apps/${app.id}/exec/${execId}/start?${searchParams.toString()}`,
                  method: 'GET',
                  headers: {
                      'Connection': 'Upgrade',
                      'Upgrade': 'tcp'
                  },
                  rejectUnauthorized
              }, function handler(res) {
                  if (res.statusCode === 403) exit('Unauthorized.'); // only admin or only owner (for docker addon)
          
                  exit('Could not upgrade connection to tcp. http status:', res.statusCode);
              });
          
              req.on('upgrade', function (resThatShouldNotBeUsed, socket /*, upgradeHead*/) {
                  // do not use res here! it's all socket from here on
                  socket.on('error', exit);
          
                  socket.setNoDelay(true);
                  socket.setKeepAlive(true);
          
                  if (tty) {
                      stdin.setRawMode(true);
                      stdin.pipe(socket, { end: false }); // the remote will close the connection
                      socket.pipe(stdout); // in tty mode, stdout/stderr is merged
                      socket.on('end', exitWithCode); // server closed the socket
                  } else { // create stdin process on demand
                      if (typeof stdin === 'function') stdin = stdin();
          
                      stdin.on('data', function (d) {
                          var buf = Buffer.alloc(4);
                          buf.writeUInt32BE(d.length, 0 /* offset */);
                          socket.write(buf);
                          socket.write(d);
                      });
                      stdin.on('end', function () {
                          var buf = Buffer.alloc(4);
                          buf.writeUInt32BE(0, 0 /* offset */);
                          socket.write(buf);
                      });
          
                      stdout.on('close', exitWithCode); // this is only emitted when stdout is a file and not the terminal
          
                      demuxStream(socket, stdout, process.stderr); // can get separate streams in non-tty mode
                      socket.on('end', function () {  // server closed the socket
                          if (typeof stdin.end === 'function') stdin.end(); // required for this process to 'exit' cleanly. do not call exit() because writes may not have finished . the type check is required for when stdin: 'ignore' in execSync, not sure why
                          if (stdout !== process.stdout) stdout.end(); // for push stream
          
                          socket.end();
          
                          // process._getActiveHandles(); process._getActiveRequests();
                          if (stdout === process.stdout) setImmediate(exitWithCode); // otherwise, we rely on the 'close' event above
                      });
                  }
              });
          
              req.on('error', exit); // could not make a request
              req.end(); // this makes the request
          

          From a little debugging I got the API path:

          /api/v1/apps/$APPID/exec/$EXECID/start?rows=21&columns=257&tty=false
          

          But when CURL'ing this:

          curl "https://my.$DOMAIN.TLD/api/v1/apps/$APPID/exec/$EXECID/start?rows=21&columns=257&tty=false" \
            -H "Authorization: Bearer $APITOKEN" \
            -H 'content-type: application/json'
          {
            "status": "Not Found",
            "message": "exec requires TCP upgrade"
          }
          

          And I am not sure how to "TCP upgrade" the curl request.
          I will ask the team.

          1 Reply Last reply
          1

          Hello! It looks like you're interested in this conversation, but you don't have an account yet.

          Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

          With your input, this post could be even better 💗

          Register Login
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Bookmarks
          • Search