1 module mongostore;
2 
3 import vibe.http.session;
4 import vibe.db.mongo.mongo;
5 import vibe.db.mongo.database;
6 import vibe.db.mongo.client;
7 import vibe.db.mongo.connection;
8 import vibe.data.bson;
9 import std.variant;
10 
11 /// Session class for `HTTPServerSettings.sessionStore`
12 final class MongoSessionStore : SessionStore
13 {
14 public:
15 	///
16 	this(string host, string database, string collection = "sessions_")
17 	{
18 		_collection = connectMongoDB(host).getDatabase(database)[collection];
19 	}
20 
21 	///
22 	this(MongoClient client, string database, string collection = "sessions_")
23 	{
24 		_collection = client.getDatabase(database)[collection];
25 	}
26 
27 	///
28 	this(MongoDatabase database, string collection = "sessions_")
29 	{
30 		_collection = database[collection];
31 	}
32 
33 	///
34 	this(MongoCollection collection)
35 	{
36 		_collection = collection;
37 	}
38 
39 	@property SessionStorageType storageType() const
40 	{
41 		return SessionStorageType.bson;
42 	}
43 
44 	Session create()
45 	{
46 		auto s = createSessionInstance();
47 		_collection.update(["id" : s.id], Bson(["session" : Bson(null)]), UpdateFlags.Upsert);
48 		return s;
49 	}
50 
51 	Session open(string id)
52 	{
53 		return _collection.findOne(["id" : id]).isNull ? Session.init : createSessionInstance(id);
54 	}
55 
56 	void set(string id, string key, Variant value)
57 	{
58 		_collection.update(["id" : id],
59 			Bson(["$set" : Bson(["session." ~ key.makeKey : value.get!Bson])]), UpdateFlags.Upsert);
60 	}
61 
62 	Variant get(string id, string key, lazy Variant defaultVal)
63 	{
64 		auto v = _collection.findOne(["id" : id])["session"].tryIndex(key.makeKey);
65 		return v.isNull ? defaultVal : Variant(v.get);
66 	}
67 
68 	bool isKeySet(string id, string key)
69 	{
70 		return !_collection.findOne(Bson(["id" : Bson(id),
71 			"session." ~ key.makeKey : Bson(["$exists" : Bson(true)])])).isNull;
72 	}
73 
74 	void destroy(string id)
75 	{
76 		_collection.remove(["id" : id]);
77 	}
78 
79 	int iterateSession(string id, scope int delegate(string key) del)
80 	{
81 		auto v = _collection.findOne(["id" : id]);
82 		foreach (string key, _; v["session"])
83 			if (auto ret = del(key))
84 				return ret;
85 		return 0;
86 	}
87 
88 private:
89 	MongoCollection _collection;
90 }
91 
92 private string makeKey(string key)
93 {
94 	if (key.length == 0)
95 		return "_";
96 	if (key[0] == '$')
97 		return "_" ~ key;
98 	return key;
99 }