Git Product home page Git Product logo

radiks-server's Introduction

radiks-server

radiks.js

Introduction

Radiks-server is a pre-built server to index and serve data that lives in decentralized services. Specifically, it is built to index data that is stored in Gaia, and created using the front-end companion library, radiks.js.

Because Gaia is just a key-value store, many applications end up needing to store an 'index' of all underlying data, in order to query it in a performant and flexible way.

Privacy

Radiks is designed to store highly private information. Because radiks.js encrypts all sensitive data before it ever leaves the client, this server ends up being a 'dumb' database that simply stores all encrypted data in an easily-queryable format.

This means that the server is only able to return queries for unencrypted data. Radiks.js is designed to be able to query for non-private information, and then decrypt the sensitive information on the client.

Multi-user scenarios

Many decentralized apps include publicly sharable information that is created with the intent of sharing that data with the world. In these situations, you want to be able to query across all user's data, using complicated queries like text search, joins, and filters.

For example, consider a Twitter-clone app. You have many different users creating their own tweets, and those tweets are stored in their own storage backends. This ensures that the user has full control and ownership of their data. You still need a central server to keep track of everyone's tweets, so that you can serve combined timelines and perform searches. Radiks-server excels in this scenario.

Authorization

Although Radiks-server is mostly a 'dumb' database that stores an index of decentralized data, there are specific authorization rules that only allow writes with the correct demonstration that the user owns the data they're writing.

Radiks.js creates and manages 'signing keys' that it uses to sign all writes that a user performs. Radiks-server is aware of this mechanism, and validates all signatures before performing a write. This guarantees that a user is not able to over-write a different user's data.

Radiks-server also is built to support writes in a collaborative, but private, situation. For example, consider a collaborative document editing application, where users can create 'organizations' and invite users to that organization. All users in that organization have read and write priveleges to data related to that organization. These organizations have single 'shared key' that is used to sign and encrypt data. When an organization administrator needs to remove a user from the group, they'll revoke a previous key and create a new one. Radiks is aware of these relationships, and will only support writes that are signed with the current active key related to a group.

Use with built-in CLI server

Radiks-server is a node.js application that uses MongoDB as an underlying database. The easiest way to run radiks-server is to use the pre-packaged node.js server that is included with this npm package.

In the future, Radiks-server will support various different databases, but right now only MongoDB is supported.

  1. Install and run MongoDB 3.6 or higher.

    You must use MongoDB >=3.6, because they fixed an issue with naming patterns in keys.

    If you are testing on a local workstation, you can install locally or use a docker image. To install, visit their download page. You can also download MongoDB using your favorite package manager. On Mac OS, homebrew is recommended.

  2. On your MongoDB instance, create a database for your application data.

  3. Create a username/password combination with root privileges on your new database.

  4. Install the radiks-server on a workstation or server.

    npm install -g radiks-server

    Or, if you prefer yarn:

    yarn global add radiks-server
  5. Create an MONGODB_URI environment variable on the same machine where you are running the radiks-server.

    Use the mongodb://username:password@host:port/db_name format for your variable. For example, to set this variable in a bash shell:

    export MONGODB_URI="mongodb://admin:[email protected]:27017/mycoolapp"

    The default port for Mongodb is 27017, your instance may be configured differently. By default, Radiks-server will use 'mongodb://localhost:27017/radiks-server' as the MONGODB_URI value. This is suitable for local testing, but in production, you'll want to change the hostname and possible the database name.

  6. Run radiks-server in the command line to start a server.

    The radiks-server defaults to running on port 1260, but you can use the PORT environment variable to modify this.

  7. Configure your application to use your radiks-server.

    To configure your applciation as a radiks client, use code that looks like this when starting up your application:

     import { UserSession, AppConfig } from 'blockstack';
     import { configure } from 'radiks';
    
     const userSession = new UserSession({
       appConfig: new AppConfig(['store_write', 'publish_data'])
     })
    
     configure({
       apiServer: 'http://my-radiks-server.com',
       userSession
     });

    For more information on configuring and writing a Radiks a client application, see the Radiks client repository.

  8. Build and run your application.

Running a custom Radiks-server

If you're using an express.js server to run your application, it's probably easiest to use the Radiks-server middleware. This way, you won't have to run a separate application server and Radiks server.

Radiks-server includes an easy-to-use middleware that you can include in your application:

const express = require('express');

const { setup } = require('radiks-server');

const app = express();

setup().then(RadiksController => {
  app.use('/radiks', RadiksController);
});

The setup method returns a promise, and that promise resolves to the actual middleware that your server can use. This is because it first connects to MongoDB, and then sets up the middleware with that database connection.

The setup function accepts an options object as the first argument. Right now, the only option supported is mongoDBUrl. If you aren't using environment variables, you can explicitly pass in a MongoDB URL here:

setup({
  mongoDBUrl: 'mongodb://localhost:27017/my-custom-database',
}).then(RadiksController => {
  app.use('/radiks', RadiksController);
});

Accessing the MongoDB Collection

Using getDB to manually connecting to the MongoDB collection

Radiks-server keeps all models inside of a collection. You can use the getDB function to access this collection. See the MongoDB Collection reference for documentation about how you can interact with this collection.

const { getDB } = require('radiks-server');

const mongo = await getDB(MONGODB_URL);

Migration from Firebase (or anywhere else)

Migrating data from Firebase to Radiks-server is simple and painless. You can create a script file to fetch all the firebase data using their API. Then, you can use your MONGOD_URI config to use the mongodb npm package.

// Script for transfering users from Firebase to Radiks-server

const { getDB } = require('radiks-server');
const { mongoURI } = require('......'); // How you import/require your mongoURI is up to you

const migrate = async () => {
  // `mongo` is a reference to the MongoDB collection that radiks-server uses.
  // You can add or edit or update data as necessary.
  const mongo = await getDB(mongoURI);

  /**
   * Call code to get your users from firebase
   * const users = await getUsersFromFirebase();
   * OR grab the Firebase JSON file and set users to that value
   * How you saved your user data will proably be different than the example below
   */

  const users = {
    '-LV1HAQToANRvhysSClr': {
      blockstackId: '1N1DzKgizU4rCEaxAU21EgMaHGB5hprcBM',
      username: 'kkomaz.id',
    },
  };

  const usersToInsert = Object.values(users).map(user => {
    const { username } = user;
    const doc = {
      username,
      _id: username,
      radiksType: 'BlockstackUser',
    };
    const op = {
      updateOne: {
        filter: {
          _id: username,
        },
        update: {
          $setOnInsert: doc,
        },
        upsert: true,
      },
    };
    return op;
  });

  await mongo.bulkWrite(usersToInsert);
};

migrate()
  .then(() => {
    console.log('Done!');
    process.exit();
  })
  .catch(error => {
    console.error(error);
    process.exit();
  });

Options

You can specify some options while initiating the Radiks server.

const { setup } = require('radiks-server');

setup({
  ...myOptions,
});

Available options:

  • mongoDBUrl - The MongoDB URL for the Radiks server
  • maxLimit - The maximum limit field used inside the mongo queries - default to 1000

radiks-server's People

Contributors

dependabot[bot] avatar hstove avatar pradel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

radiks-server's Issues

Error accessing data

This error is showing up in the Stackit test app. @hstove Sahana believes it is the server not the code.

  1. Install the code from this repo: https://github.com/moxiegirl/radix-code
  2. Install mongodb with home brew
  3. Install the latest radiks-server
  4. Start the code npm start
  5. Create a block

image

When the create returns the user to the dashboard:

not available
 bn.js:598 Uncaught (in promise) TypeError: Cannot read property '-1' of null at BN.bitLength (bn.js:598) at Point._hasDoubles (base.js:303) at Point.mul (short.js:403) at KeyPair.getPublic (key.js:63) at encryptECIES (ec.js:114) at helpers.js:138 at Array.forEach (<anonymous>) at encryptObject (helpers.js:121) at async http:/127.0.0.…js/0.chunk.js:77439 

You should see the create in the database so the connection does work. As the create block stores data:

image

GroupMembership Error Validator

there is something wrong with creating group membership on the beta radiks server , it fails on the validator and message error is:
message: "Error when validating: No signing key is present with id: '[object Object]'"

Delete API needs to check for an updated `updatedAt` attribute

When models are updated with radiks, radiks-server checks to make sure the updatedAt field is bigger than it was before, which is a way of preventing "signature jacking", similar to how nonces are used in blockchains. The delete API doesn't have this functionality right now, and it should.

Is this still maintained?

Hello,

I was looking at this project as I'm trying to use gaia to store shareable secret documents. Amongst other things I understand this is one of Radiks Server's goals.

I noticed there's no activity going on here for quite some time so:

Is it still recommended for indexing? If not, is there any other initiative actively developed?

Thank you 👌

cc @hstove @friedger

Built in https/SSL for Radiks server

This is from the dev survey and could have two components.

A) Include built in https support to Radiks http server.

B) Add documentation specifying that Radiks is designed to be ran behind nginx where https can be handled.

@hstove feel free to mod this with better tasks or an update on this.

Working with Gaia

Please is there any resource for gathering data stored in gaia using radiks
for example if i have 100 posts stored in 20 different users gaia hub, how do i fetch all of them using gaia

and also any basic gaia+radiks setup guide

what's wrong with radisk-server after yarn add?

~$ PORT=2319 radiks-server
internal/modules/cjs/loader.js:638
throw err;
^
what's wrong with radisk-server after yarn add?

npm install -g radiks-server

or, if you use yarn

yarn global add radiks-server

Error: Cannot find module '../index'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:636:15)
at Function.Module._load (internal/modules/cjs/loader.js:562:25)
at Module.require (internal/modules/cjs/loader.js:690:17)
at require (internal/modules/cjs/helpers.js:25:18)
at Object. (/usr/lib/node_modules/radiks-server/bin/radiks-server.js:5:19)
at Module._compile (internal/modules/cjs/loader.js:776:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
at Module.load (internal/modules/cjs/loader.js:653:32)
at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
at Function.Module._load (internal/modules/cjs/loader.js:585:3)

Error in JSON serializations into URL parameters

From enginnering thread Public slack.

xanderjakeq

how do I make an or query with radiks like the one described here:
https://docs.mongodb.com/manual/reference/operator/query/or/ (edited)

Is there a way I could do this @hank?

Hank:

yes - you can basically enter any query you’d pass to the mongoDB find API. just use the equivalent JSON query syntax in fetchList or whatever you’re using

so

find.({ $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] })

The equivalent would be

`fetchList({ $or: [ { }, { }, ... , { } ] })``

Hank
yeah i think that should work.

try it out and confirm?

xanderjakeq 21 hours ago
okay thanks!
I have this

fetchList({
			$or: [
				{
					offset,
					limit,
					author: {
						$ne: username
					},
					notif_for: subbed_models,
					sort: '-createdAt'
				},
				{
					offset,
					limit,
					author: {
						$ne: username
					},
					mentions: username,
					sort: '-createdAt'
				}
			]
		});

but I'm getting this error

VM433:1 GET http://localhost:5000/radiks/models/find?$or[][offset]=0&$or[][limit]=20&$or[][author][$ne]=xanderjakeq2.id.blockstack&$or[][notif_for][]=2ba0fcc064b0-45ed-9cac-d8df5054852a&[sort]=-createdAt&$or[][offset]=0&$or[][limit]=20&$or[][author][$ne]=xanderjakeq2.id.blockstack&$or[][mentions]=xanderjakeq2.id.blockstack&$or[][sort]=-createdAt&radiksType=Notification 500 (Internal Server Error)

Hank:
can you post the actual error from radiks-server?

xanderjakeq

MongoError: $or must be an array
    at Connection.<anonymous> (C:\Dev\Websites\startups\anylist\server\node_modules\mongodb\lib\core\connection\pool.js:466:61)
    at Connection.emit (events.js:189:13)
    at processMessage (C:\Dev\Websites\startups\anylist\server\node_modules\mongodb\lib\core\connection\connection.js:364:10)
    at TLSSocket.<anonymous> (C:\Dev\Websites\startups\anylist\server\node_modules\mongodb\lib\core\connection\connection.js:533:15)
    at TLSSocket.emit (events.js:189:13)
    at addChunk (_stream_readable.js:284:12)
    at readableAddChunk (_stream_readable.js:265:11)
    at TLSSocket.Readable.push (_stream_readable.js:220:10)
    at TLSWrap.onStreamRead [as onread] (internal/stream_base_commons.js:94:17)

Hank:

i see - this seems like a bug in how the JSON gets serialized into URL parameters also, you can’t put those pagination params inside of the $or. it needs to be ‘top level’ to the query. otherwise, mongoDB will be looking for models where offset = 0, for example

xanderjakeq

ahh okay is that bug easy to fix? if so, I could wait before I try doing some workarounds

Hank:

i’m not quite sure. a workaround could be to do 2 separate queries

Error: Error when validating: Tried to update a non-updatable model

I was deploying my app and i found this error on my server logs

(node:11621) DeprecationWarning: collection.find option [fields] is deprecated and will be removed in a later version.
0|server   | (node:11621) DeprecationWarning: collection.save is deprecated. Use insertOne, insertMany, updateOne, or updateMany instead.
0|server   | Error: Error when validating: Tried to update a non-updatable model
0|server   |     at errorMessage (/root/servers/dcloud/packages/server/node_modules/radiks-server/app/lib/validator.js:4:9)
0|server   |     at Validator.validatePrevious (/root/servers/dcloud/packages/server/node_modules/radiks-server/app/lib/validator.js:71:7)
0|server   |     at Validator.validate (/root/servers/dcloud/packages/server/node_modules/radiks-server/app/lib/validator.js:17:16)
0|server   |     at process._tickCallback (internal/process/next_tick.js:68:7)
0|server   | Error: Error when validating: Tried to update a non-updatable model
0|server   |     at errorMessage (/root/servers/dcloud/packages/server/node_modules/radiks-server/app/lib/validator.js:4:9)
0|server   |     at Validator.validatePrevious (/root/servers/dcloud/packages/server/node_modules/radiks-server/app/lib/validator.js:71:7)
0|server   |     at Validator.validate (/root/servers/dcloud/packages/server/node_modules/radiks-server/app/lib/validator.js:17:16)
0|server   |     at process._tickCallback (internal/process/next_tick.js:68:7)

The app routing throw a bad gateway 502 Error
the error seems that i am updating some models are not updateable, which i think is just SigningKey. which is i cannot update a SigningKey with a new private key.

but i don't do anything like that in my react app

radiksType=t on production SPA when fetching Users via fetchList

Awesome start to making developer life easier @hstove! I'm sure this is going to be heavily adopted in the future!

I set up my heroku server + heroku RADIKS server and when testing locally on my front-end SPA it works fine when fetching for a Users list via Users.fetchList()

screenshot of google chrome 2-8-19 5-23-03 pm

However, when I deploy my SPA to production via netlify I noticed the query for users get shortened to a single character string t

screenshot of google chrome 2-8-19 5-23-05 pm

Not exactly sure what's going on but would love some insight on how to resolve this!

Error when validating signing key

Hi @hstove you have created an amazing service!

Unfortunately, while using radiks-server with radiks I start to experience strange behavior:
await userSession.handlePendingSignIn(); await User.createWithCurrentUser();

as far as I understand the last line of code trying to fetch user from mongo with help of current user id, unfortunately, something changed and this method isn't working correctly right now.

Exception from radiks-server

(node:34832) UnhandledPromiseRejectionWarning: Error: Error when validating: No signing key is present with id: '[object Object]' at errorMessage (\AppData\Roaming\npm\node_modules\radiks-server\app\lib\validator.js:4:9) at Validator.validateSignature (\AppData\Roaming\npm\node_modules\radiks-server\app\lib\validator.js:47:9) at process._tickCallback (internal/process/next_tick.js:68:7) (node:34832) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)

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.