firebase-queue icon indicating copy to clipboard operation
firebase-queue copied to clipboard

Authorization rules in bolt

Open tirsen opened this issue 9 years ago • 5 comments

We're using the bolt compiler for our authorization rules. Can we get a port of the authorization rules to bolt please?

tirsen avatar Mar 11 '16 09:03 tirsen

+1

wconnorwalsh avatar Mar 21 '16 19:03 wconnorwalsh

Here is my attempt, seem to work. Customize to your own needs. Not sure about the ErrorDetail type, has it is not validated in the original format of the queue rules.

//
//
// Rules for the workers queue
//
//
path /queue/tasks {
    read() { auth.canProcessTasks }
    write() { auth.canAddTasks || auth.canProcessTasks }
    index() { ['_state'] }

    /{taskId} is Task {
        validate() {
            // Customize to your needs the following line
            this.hasChildren(['_property_1', ..., '_property_n']) || 
            (auth.canProcessTasks &&
                this.hasChildren(['_state', '_state_changed', '_progress']))
        }
    }
}

path /queue/specs {
    read() { auth.canAddSpecs || auth.canProcessTasks }
    write() { auth.canAddSpecs }

    /{specId} is Spec
}

type Task {
    _state: String | Null,
    _state_changed: InitialTimestamp | Null,
    _owner: String | Null,
    _progress: Percent | Null,
    _error_details: ErrorDetail | Null,
    _id: String | Null,
    _property_1: XXX, // Change with custom properties validation
    ...               // Change with custom properties validation
    _property_n: XXX, // Change with custom properties validation
}

type Spec {
    start_state: String | Null,
    in_progress_state: String,
    finished_state: String | Null,
    error_state: String | Null,
    timeout: PositiveNumber | Null,
}

type ErrorDetail {
    error: String | Null,
    error_stack: String | Null,
    previous_state: String | Null,
    original_task: Anything | Null,
    attempts: PositiveNumber | Null
}

type InitialTimestamp extends Number {
  validate() { noChange(this) || withInitialCondition(this, this == now) }
}

type PositiveNumber extends Number {
    validate() { this >= 0 }
}

type Percent extends Number {
    validate() { this <= 100 }
}

// Type `Any` has a bug, this is a workaround
// see https://github.com/firebase/bolt/issues/111
type Anything {
    validate() {
        this.isString() || this.isNumber() || this.isBoolean() || this.hasChildren()
    }
}

withInitialCondition(ref, exp) { isNew(ref) && exp }

isNew(ref) { prior(ref) == null }

noChange(ref) { ref == prior(ref) }

pandaiolo avatar Jul 05 '16 14:07 pandaiolo

Thoughts on why firebase-queue should not exist in our bolt rules

  • You don't own the type so upgrades of this third party lib would seem error prone. I would recommend to not specify an [is Type] rule.
  • authorization rules only should be specified on the '/queue' path.
    read() { auth.canAdministerQueue || auth.canProcessQueue }
    write() { auth.canAdministerQueue || auth.canProcessQueue }
  • specs - is a devops 1 time migration script using a custom firebase token with canAdministerQueue claim.
  • tasks - should not be exposed to the browser client. This is an ongoing backend process that watches a path and writes to a given queue/task using canAdministerQueue claim.

What I am having problems with is the last list item. How can I make it atomic? Ideally, I would want firebase to support a trigger so as a collection is appended I could auto append the task queue. Until then, it seems we may need firebase-queue-watcher™ to watch a collection and append the queue task collection. Is there a project that already mirrors an existing collection, recovers on restarts where it left off?

leblancmeneses avatar Aug 03 '16 12:08 leblancmeneses

I fixed the Any bug in the Bolt repo yesterday if you want to try it out (I will release it via npm along with other bug fixes in the next day or so - probably as version 0.8.1).

BTW - while it currently works to call methods like hasChildren() and isBoolean() in your own validate methods, it's more idiomatic to use type statements.

// This Bolt definition ...
type Anything extends String | Number | Boolean | Object;
path /x is Anything;

// ... produces this JSON output:
{
  "rules": {
    "x": {
      ".validate": "newData.isString() || newData.isNumber() || newData.isBoolean() || newData.hasChildren()"
    }
  }
}

mckoss avatar Aug 04 '16 16:08 mckoss

@mckoss Is there a way to get "$other": to be replaced with a custom expression?

"$other":{ '.validate': "auth != null && auth.uid == 'feature-worker'" }

benefits:

  1. Forces the web client to match the Type specified on the path.
  2. My Type doesn't care about firebase-queue internal data structures.
  3. Allows my firebase queue worker to be able to write other queue specific properties when limiting write access with databaseAuthVariableOverride: { uid: "feature-worker" } to the rest of my database.

leblancmeneses avatar Oct 18 '16 04:10 leblancmeneses