CASBIN url subset block - casbin

I have following policies:
p, alice, /alice_data/:id/using, GET
p, bob, /alice_data/*, GET
My current enforcer enforcement result:
alice, /alice_data/hello, GET -> True
bob, /alice_data/123/using, GET -> True
I need to block bob for /alice_data/:id/using
alice, /alice_data/hello, GET -> i want it to be True
bob, /alice_data/123/using, GET -> i want it to be **False**
since /alice_data/123/using is a subset of /alice_data/* , but i want to block bob for /alice_data/123/using, can I do that ?? please guide

To control whether /alice_data/123/using matches /alice_data/*, you need to use regexMatch or define your own keyMatch: https://casbin.org/docs/en/function

Related

Data structure MongoDB for Insurance policies

I am trying to have some feedback about the best way to organize data for an insurance company (and in general).
I am using MongoDB and i'm unsure about a thing.
lets say i have different prices for different coverages on the same policy, on top of that various cases based on the annual income of the company who will sign the policy.
#1. Coverage -> 5.000.000 - Annual income -> 1.000.000 - price -> 500
#2. Coverage -> 5.000.000 - Annual income -> 1.500.000 - price -> 550
Then i can add extensions to that policy (in this case just 4 types)
#1.Basic extension -> 120 - Advanced extension -> 150
#1.Basic extension -> 150 - Advanced extension -> 170
I was thing about saving every policy in a collection, everyone with their characteristics.
So, lets take this one as an example.
Collection: policies
Entry:
id
name: name of the policy as it is written in the docs
prices: [{id: 0, price: 500, income_range: [0, 1.000.000], coverage_range: [0,5.000.000], extensions: [120, 150]}, {{id: 1, price: 550, income_range: [1.000.001, 1.500.000], coverage_range: [0,5.000.000], extensions: [150, 170]}
other_general_stuff
OR
Collection: policies
Entry:
id
name: name of the policy as it is written in the docs
prices: [{id: 0, price: 500, income_range: 0, coverage_range: 0, extensions: l1}, {{id: 1, price: 550, income_range: 1, coverage_range: 0, extensions: l2}
income_ranges: [{id: 0, range: [0, 1.000.000]}, {id: 1, range: [1.000.001, 1.500.000]}]
cover_ranges: [{id: 0, range: [0, 5.000.000]}, {id: 1, range: [5.000.000, 7.000.000]}]
extensions: {l1: {basic: 120, adv: 150}, l2: {basic: 150, adv: 170}}
I mean considering there are different products this i just a tiny example, but what concerns me is for ex. the ranges property, is it ok in this type of db to scructure it like the second example, is there a way of accessing those property in an easy way, or is it better to write the entire thing directly into the 'prices field'.
I have not much experience, so I am trying to figure out what is the best practice to follow.
I know that there are many possible solutions, but is this entirely wrong? Can someone give me a feedback or point me to some nice resources.
Thank you

Questions with a fixed and pre-specified number of true and false answers

I would like to use the R/exams package to create multiple-choice questions for a Moodle quiz. However, I am not sure whether R/exams can always choose a fixed number of correct items. Suppose we have a question with the following items:
Answerlist
----------
* A (correct)
* B (correct)
* C (correct)
* D (incorrect)
* E (incorrect)
* F (incorrect)
* G (incorrect)
* H (incorrect)
* I (incorrect)
In this example, I would like R/exams to choose exactly 2 correct answers and exactly 6 incorrect answers. Is that possible?
Yes, it is possible but you need to write a little bit of R code for it. If you only set exshuffle to 8, then R/exams would sample 8 items and use only the restriction that there is at least one true and at least one false item.
If one wants further restrictions in the sampling, then generally these can be implemented by writing the corresponding R code for it. In this particular case I would do the following:
Sample 2 correct items.
Sample 6 correct items.
Put everything into an answerlist().
Set exshuffle to TRUE so that the 8 selected items are permuted one more time by R.
The corresponding Rmd exercise then looks like this:
```{r, include = FALSE}
correct <- c(
"A (correct)",
"B (correct)",
"C (correct)"
)
correct <- sample(correct, 2)
incorrect <- c(
"D (incorrect)",
"E (incorrect)",
"F (incorrect)",
"G (incorrect)",
"H (incorrect)",
"I (incorrect)"
)
incorrect <- sample(incorrect, 6)
```
Question
========
Please select the correct items.
```{r, echo = FALSE, results = "asis"}
answerlist(c(correct, incorrect), markup = "markdown")
```
Meta-information
================
exname: Custom item sampling
extype: mchoice
exsolution: 11000000
exshuffle: TRUE
When set up like this, it is also easily possibly to extend the list of initial correct and incorrect items arbitrarily. The rest of the code will always assure that you get 2 out of the correct and 6 out of the incorrect items.
Nothing in this is specific to exams2moodle(), i.e., you can use this exercise with any exams2xyz() interface (except exams2nops() which just supports item lists with up to 5 items).

take(n) doesn't have effect after groupBy in RxJava2

I am trying to group several model instances by name and then use take(n) to take only certain items per group, but somehow the take has no effect on GroupedObservable. Here is the code
Let's assume this contains a list with 10 items and 5 have the name "apple" and the other 5 have the name "pear"
Observable<Item> items....
Observable<Item> groupedItems = items.groupBy(Item::name)
.flatMap(it -> it.take(2));
So I imagine groupedItems has to emit 2 "apples" and 2 "pears", but it has all of them instead.
Is there something which I am getting wrong, do I need to do it differently?
Cancelled groups are recreated when the same key is encountered again. You need to make sure the group is not stopped and you'd have to ignore further items in some fashion:
source.groupBy(func)
.flatMap(group ->
group.publish(p -> p.take(5).mergeWith(p.ignoreElements()))
);

Understanding how to read each-right and each-left combined in kdb

From q for mortals, i'm struggling to understand how to read this, and understand it logically.
1 2 3,/:\:10 20
I understand the result is a cross product when in full form: raze 1 2 3,/:\:10 20.
But reading from left to right, I'm currently lost at understanding what this yields (in my head)
\:10 20
combined with 1 2 3,/: ??
Help in understanding how to read this clearly (in words or clear logic) would be appreciated.
I found myself saying the following in my head whilst I program the syntax in q. q works from right to left.
Internal Monologue -> Join the string on the right onto each of the strings on the left
code -> "ABC",\:"-D"
result -> "A-D"
"B-D"
"C-D"
I think that's an easy way to understand it. 'join' can be replaced with whatever...
Internal Monologue -> Does the string on the right match any of the strings on the left
code -> ("Cat";"Dog";"CAT";"dog")~\:"CAT"
result -> 0010b
Each-right is the same concept and combining them is straightforward also;
Internal Monologue -> Does each of the strings on the right match each of the strings on the left
code -> ("Cat";"Dog";"CAT";"dog")~\:/:("CAT";"Dog")
result -> 0010b
0100b
So in your example 1 2 3,/:\:10 20 - you're saying 'Join each of the elements on the right to each of the elements on the left'
Hope this helps!!
EDIT To add a real world example.... - consider the following table
q)show tab:([] upper syms:10?`2; names:10?("Robert";"John";"Peter";"Jenny"); amount:10?til 10)
syms names amount
--------------------
CF "Peter" 8
BP "Robert" 1
IC "John" 9
IN "John" 5
NM "Peter" 4
OJ "Jenny" 6
BJ "Robert" 6
KH "John" 1
HJ "Peter" 8
LH "John" 5
q)
I you want to get all records where the name is Robert, you can do; select from tab where names like "Robert"
But if you want to get the results where the name is either Robert or John, then it is a perfect scenario to use our each-left and each-right.
Consider the names column - it's a list of strings (a list where each element is a list of chars). What we want to ask is 'does any of the strings in the names column match any of the strings we want to find'... that translates to (namesList)~\:/:(list;of;names;to;find). Here's the steps;
q)(tab`names)~\:/:("Robert";"John")
0100001000b
0011000101b
From that result we want a compiled list of booleans where each element is true of it is true for Robert OR John - for example, if you look at index 1 of both lists, it's 1b for Robert and 0b for John - in our result, the value at index 1 should be 1b. Index 2 should be 1b, index3 should be 1b, index4 should be 0b etc... To do this, we can apply the any function (or max or sum!). The result is then;
q)any(tab`names)~\:/:("Robert";"John")
0111001101b
Putting it all together, we get;
q)select from tab where any names~\:/:("Robert";"John")
syms names amount
--------------------
BP "Robert" 1
IC "John" 9
IN "John" 5
BJ "Robert" 6
KH "John" 1
LH "John" 5
q)
Firstly, q is executed (and hence generally read) right to left. This means that it's interpreting the \: as a modifier to be applied to the previous function, which itself is a simple join modified by the /: adverb. So the way to read this is "Apply join each-right to each of the left-hand arguments."
In this case, you're applying the two adverbs to the join - \:10 20 on its own has no real meaning here.
I find it helpful to also look at the converse case 1 2 3,\:/:10 20, running that code produces a 2x6 matrix, which I'd describe more like "apply join each-left to each of the right hand arguments" ... I hope that makes sense.
An alternative syntax which also might help is ,/:\:[1 2 3;10 20] - this might be useful as it makes it very clear what the function you're applying is, and is equivalent to your in-place notation.

Combine Records in Purescript

Given I have the folowing records in purescript:
let name = {name: "Jim"}
let age = {age: 37}
is it possible to combine those two records some how in a generic way?
Something like:
name 'comb' age
such that I get the following record:
{name: "Jim", age: 37}
Somehow it seems to be possible with the Eff rowtype, but I'm curious if it would be possible with 'normal' records. I'm new to purescript and it's record syntax.
Thanks a lot.
EDIT:
It seems that currently the official package for handling record manipulations is purescript-record - you can find Builder.purs there which provides merge and build functions:
> import Data.Record.Builder (build, merge)
> name = {name: "Jim"}
> age = {age: 37}
> :t (build (merge age) name)
{ name :: String
, age :: Int
}
API NOTE:
This API looks overcomplicated at first glance - especially when you compare it to simple unionMerge name age call (unionMerge is intoduced at the end of this answer). The reason behind Builder existence (and so this API) is performance. I can assure you that this:
> build (merge name >>> merge age) {email: "someone#example.com"}
creates only one new record. But this:
> unionMerge name (unionMerge age {email: "someone#example.com"})
creates two records during execution.
What is even more interesting is how Builder, build and merge are implemented - Builder is newtype wrapper around a function (and its composition is just a function composition) and build is just a function application on copied version of the record:
newtype Builder a b = Builder (a -> b)
build (Builder b) r1 = b (copyRecord r1)
In merge there is unsafeMerge performed:
merge r2 = Builder \r1 -> unsafeMerge r1 r2
So why are we gaining here anything?? Because we can be sure that intermediate results can't escape function scope and that every value is consumed exactly once in builder chain. Therefore we can perform all transformations "in place" in a mutable manner. In other words this intermediate value:
> intermediate = unionMerge name {email: "someone#example.com"}
> unionMerge age intermediate
can't be "extracted" from here:
> build (merge name >>> merge age) {email: "someone#example.com"}
and it is only consumed once by the next builder, namely merge age.
TYPESYSTEM COMMENT:
It seems that Purescript type system can handle this now thanks to the Union type class from Prim:
The Union type class is used to compute the union of two rows
of types (left-biased, including duplicates).
The third type argument represents the union of the first two.
Which has this "magic type" (source: slide 23):
Union r1 r2 r3 | r1 r2 -> r3, r1 r3 -> r2
OLD METHOD (still valid but not preferred):
There is purescript-records package which exposes unionMerge which does exactly what you want (in new psci we don't have to use let):
> import Data.Record (unionMerge)
> name = {name: "Jim"}
> age = {age: 37}
> :t (unionMerge age name)
{ name :: String
, age :: Int
}
note: When this answer was accepted, it was true, but now we do have the row constraints it mentions, and a library for manipulating records that includes merges/unions: https://github.com/purescript/purescript-record
It's not possible to do this at the moment, as we don't have a way of saying that a row lacks some label or other. It is possible to have an open record type:
something :: forall r. { name :: String | r } -> ...
But this only allows us to accept a record with name and any other labels, it doesn't help us out if we want to combine, extend, or subtract from records as it stands.
The issue with combining arbitrary records is we'd have a type signature like this:
comb :: forall r1 r2. { | r1 } -> { | r2 } -> ???
We need some way to say the result (???) is the union of r1 and r2, but also we'd perhaps want to say that r1's labels do not overlap with r2's.
In the future this may be possible via row constraints.