Skip to content

Commit 6d2fecd

Browse files
committed
init project
0 parents  commit 6d2fecd

12 files changed

Lines changed: 631 additions & 0 deletions

File tree

.gitignore

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Created by .ignore support plugin (hsz.mobi)
2+
### Java template
3+
# Compiled class file
4+
*.class
5+
6+
# Log file
7+
*.log
8+
9+
# BlueJ files
10+
*.ctxt
11+
12+
# Mobile Tools for Java (J2ME)
13+
.mtj.tmp/
14+
15+
# Package Files #
16+
*.jar
17+
*.war
18+
*.nar
19+
*.ear
20+
*.zip
21+
*.tar.gz
22+
*.rar
23+
24+
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
25+
hs_err_pid*
26+
27+
*.iml
28+
29+
# Mongo Explorer plugin
30+
.idea
31+
32+

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
jcasbin-mongodb-adapter
2+
===
3+
MongoDB policy storage, implemented as an adapter for [jcasbin](https://github.com/casbin/jcasbin).

examples/rbac_model.conf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, obj, act
6+
7+
[role_definition]
8+
g = _, _
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

examples/rbac_policy.csv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
p, alice, data1, read
2+
p, bob, data2, write
3+
p, data2_admin, data2, read
4+
p, data2_admin, data2, write
5+
g, alice, data2_admin
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, dom, obj, act
3+
4+
[policy_definition]
5+
p = sub, dom, obj, act
6+
7+
[role_definition]
8+
g = _, _, _
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
p, admin, domain1, data1, read
2+
p, admin, domain1, data1, write
3+
p, admin, domain2, data2, read
4+
p, admin, domain2, data2, write
5+
g, alice, admin, domain1
6+
g, bob, admin, domain2

pom.xml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>org.jim</groupId>
8+
<artifactId>jcasbin-mongo-adapter</artifactId>
9+
<version>1.0-SNAPSHOT</version>
10+
11+
<properties>
12+
<maven.compiler.source>8</maven.compiler.source>
13+
<maven.compiler.target>8</maven.compiler.target>
14+
</properties>
15+
<dependencies>
16+
<dependency>
17+
<groupId>org.projectlombok</groupId>
18+
<artifactId>lombok</artifactId>
19+
<version>1.18.18</version>
20+
<scope>provided</scope>
21+
</dependency>
22+
<dependency>
23+
<groupId>org.mongodb</groupId>
24+
<artifactId>mongodb-driver-sync</artifactId>
25+
<version>4.2.2</version>
26+
<scope>provided</scope>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.casbin</groupId>
30+
<artifactId>jcasbin</artifactId>
31+
<version>1.7.4</version>
32+
</dependency>
33+
<dependency>
34+
<groupId>junit</groupId>
35+
<artifactId>junit</artifactId>
36+
<version>4.13.1</version>
37+
<scope>test</scope>
38+
</dependency>
39+
</dependencies>
40+
</project>
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package org.jim.jcasbin;
2+
3+
import com.mongodb.MongoClientSettings;
4+
import com.mongodb.client.FindIterable;
5+
import com.mongodb.client.MongoClient;
6+
import com.mongodb.client.MongoCollection;
7+
import org.bson.Document;
8+
import org.bson.codecs.configuration.CodecRegistry;
9+
import org.bson.codecs.pojo.PojoCodecProvider;
10+
import org.casbin.jcasbin.model.Model;
11+
import org.casbin.jcasbin.persist.Adapter;
12+
import org.jim.jcasbin.domain.CasbinRule;
13+
import org.slf4j.Logger;
14+
import org.slf4j.LoggerFactory;
15+
16+
import java.util.ArrayList;
17+
import java.util.List;
18+
import java.util.Map;
19+
import java.util.Optional;
20+
import java.util.stream.Collectors;
21+
import java.util.stream.StreamSupport;
22+
23+
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
24+
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
25+
26+
/**
27+
* MongoAdapter is the Mongodb adapter for jCasbin.
28+
* It can load policy from MongoDB or save policy to it.
29+
*
30+
* @author JimZhang
31+
* @since 2021/3/23
32+
* Description:
33+
*/
34+
35+
public class MongoAdapter implements Adapter {
36+
private static final String DEFAULT_DB_NAME = "casbin";
37+
private static final String DEFAULT_COL_NAME = "casbin_rule";
38+
private static final Logger log = LoggerFactory.getLogger(MongoAdapter.class);
39+
private static final CodecRegistry POJO_CODEC_REGISTRY = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
40+
fromProviders(PojoCodecProvider.builder().automatic(true).build()));
41+
42+
private static String orDefault(String str, String defaultStr) {
43+
return str == null || str.trim().isEmpty() ? defaultStr : str;
44+
}
45+
46+
private static Optional<CasbinRule> fromListRule(List<String> rules) {
47+
if (rules.size() != 7) {
48+
log.warn("list rules size [{}] do not match pojo fields", rules.size());
49+
return Optional.empty();
50+
}
51+
CasbinRule casbinRule = new CasbinRule();
52+
for (int i = 0; i < rules.size(); i++) {
53+
casbinRule.setByIndex(i, rules.get(i));
54+
}
55+
return Optional.of(casbinRule);
56+
}
57+
58+
private final MongoClient mongoClient;
59+
private final String dbName;
60+
private final String colName;
61+
62+
63+
public MongoAdapter(MongoClient mongoClient, String dbName) {
64+
this(mongoClient, dbName, null);
65+
}
66+
67+
public MongoAdapter(MongoClient mongoClient, String dbName, String colName) {
68+
this.mongoClient = mongoClient;
69+
70+
this.dbName = orDefault(dbName, DEFAULT_DB_NAME);
71+
this.colName = orDefault(colName, DEFAULT_COL_NAME);
72+
}
73+
74+
protected void clearCollection() {
75+
this.mongoClient.getDatabase(this.dbName).getCollection(this.colName).drop();
76+
}
77+
78+
private MongoCollection<CasbinRule> getCollection() {
79+
return this.mongoClient
80+
.getDatabase(this.dbName)
81+
.withCodecRegistry(POJO_CODEC_REGISTRY)
82+
.getCollection(this.colName, CasbinRule.class);
83+
}
84+
85+
/**
86+
* 从存储加载所有策略规则
87+
* 加载时会合并重复数据
88+
*
89+
* @param model the model.
90+
*/
91+
@Override
92+
public void loadPolicy(Model model) {
93+
Map<String, ArrayList<ArrayList<String>>> policies = this.loading();
94+
policies.keySet().forEach(k -> model.model.get(k.substring(0, 1)).get(k).policy.addAll(policies.get(k)));
95+
}
96+
97+
Map<String, ArrayList<ArrayList<String>>> loading() {
98+
FindIterable<CasbinRule> findAll = this.getCollection()
99+
.find();
100+
return StreamSupport.stream(findAll.spliterator(), false)
101+
.distinct()
102+
.map(CasbinRule::toPolicy)
103+
.collect(Collectors.toMap(
104+
x -> x.get(0), y -> {
105+
ArrayList<ArrayList<String>> lists = new ArrayList<>();
106+
// 去除list第一项策略类型
107+
y.remove(0);
108+
lists.add(y);
109+
return lists;
110+
}, (oldValue, newValue) -> {
111+
oldValue.addAll(newValue);
112+
return oldValue;
113+
})
114+
);
115+
}
116+
117+
/**
118+
* 将所有策略规则保存到存储
119+
* 保存时会合并重复数据
120+
*
121+
* @param model the model.
122+
*/
123+
@Override
124+
public void savePolicy(Model model) {
125+
this.clearCollection();
126+
List<CasbinRule> casbinRules = CasbinRule.transformToCasbinRule(model);
127+
this.getCollection().insertMany(casbinRules);
128+
}
129+
130+
/**
131+
* 将策略规则添加到存储
132+
*
133+
* @param sec the section, "p" or "g".
134+
* @param ptype the policy type, "p", "p2", .. or "g", "g2", ..
135+
* @param rule the rule, like (sub, obj, act).
136+
*/
137+
@Override
138+
public void addPolicy(String sec, String ptype, List<String> rule) {
139+
this.adding(sec, ptype, rule);
140+
}
141+
142+
143+
void adding(String sec, String ptype, List<String> rule) {
144+
ArrayList<String> rules = new ArrayList<>(rule);
145+
rules.add(0, ptype);
146+
for (int i = 0; i < 6 - rule.size(); i++) {
147+
rules.add("");
148+
}
149+
Optional<CasbinRule> casbinRule = fromListRule(rules);
150+
casbinRule.ifPresent(r -> this.getCollection().insertOne(r));
151+
}
152+
153+
/**
154+
* 从存储中删除策略规则
155+
*
156+
* @param sec the section, "p" or "g".
157+
* @param ptype the policy type, "p", "p2", .. or "g", "g2", ..
158+
* @param rule the rule, like (sub, obj, act).
159+
*/
160+
@Override
161+
public void removePolicy(String sec, String ptype, List<String> rule) {
162+
if (rule.isEmpty()) return;
163+
removeFilteredPolicy(sec, ptype, 0, rule.toArray(new String[0]));
164+
165+
}
166+
167+
void removing(String sec, String ptype, int fieldIndex, String... fieldValues) {
168+
if (fieldValues.length == 0) return;
169+
Document filter = new Document("ptype", ptype);
170+
int columnIndex = fieldIndex;
171+
for (String fieldValue : fieldValues) {
172+
if (CasbinRule.hasText(fieldValue)) filter.put("v" + columnIndex, fieldValue);
173+
columnIndex++;
174+
}
175+
this.getCollection().deleteOne(filter);
176+
177+
}
178+
179+
/**
180+
* 从存储中删除当前策略指定索引后匹配的数据
181+
*
182+
* @param sec the section, "p" or "g".
183+
* @param ptype the policy type, "p", "p2", .. or "g", "g2", ..
184+
* @param fieldIndex the policy rule's start index to be matched.
185+
* @param fieldValues the field values to be matched, value ""
186+
*/
187+
@Override
188+
public void removeFilteredPolicy(String sec, String ptype, int fieldIndex, String... fieldValues) {
189+
this.removing(sec, ptype, fieldIndex, fieldValues);
190+
}
191+
}

0 commit comments

Comments
 (0)