mirror of
https://github.com/logos-storage/nim-datastore.git
synced 2026-01-04 06:33:11 +00:00
rename fsstore to fsds
This commit is contained in:
parent
c7df334836
commit
b380d09d6b
@ -1,5 +1,6 @@
|
|||||||
import std/os
|
import std/os
|
||||||
import std/sequtils
|
import std/sequtils
|
||||||
|
import std/strutils
|
||||||
import std/options
|
import std/options
|
||||||
|
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
@ -20,23 +21,27 @@ const
|
|||||||
# Paths should be matched exactly, i.e.
|
# Paths should be matched exactly, i.e.
|
||||||
# we're forbidding this dirs from being
|
# we're forbidding this dirs from being
|
||||||
# touched directly, but subdirectories
|
# touched directly, but subdirectories
|
||||||
# can still be touched
|
# can still be touched/created
|
||||||
ProtectedPaths = [
|
ProtectedPaths* = [
|
||||||
"/",
|
"/",
|
||||||
"/usr",
|
"/usr",
|
||||||
"/etc",
|
"/etc",
|
||||||
"/home",
|
"/home",
|
||||||
"/Users"]
|
"/Users"]
|
||||||
|
|
||||||
|
Allowed* =
|
||||||
|
toSeq('A'..'Z') &
|
||||||
|
toSeq('a'..'z') &
|
||||||
|
toSeq('0'..'9') &
|
||||||
|
toSeq(['/', '_', '-'])
|
||||||
|
|
||||||
type
|
type
|
||||||
FSDatastore* = ref object of Datastore
|
FSDatastore* = ref object of Datastore
|
||||||
root*: string
|
root*: string
|
||||||
ignoreProtected: bool
|
ignoreProtected: bool
|
||||||
|
depth: int
|
||||||
|
|
||||||
func checkProtected(dir: string): bool =
|
template path*(self: FSDatastore, key: Key): string =
|
||||||
dir in ProtectedPaths
|
|
||||||
|
|
||||||
proc path*(self: FSDatastore, key: Key): string =
|
|
||||||
var
|
var
|
||||||
segments: seq[string]
|
segments: seq[string]
|
||||||
|
|
||||||
@ -45,22 +50,53 @@ proc path*(self: FSDatastore, key: Key): string =
|
|||||||
segments.add ns.value
|
segments.add ns.value
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# `:` are replaced with `/`
|
||||||
segments.add(ns.field / ns.value)
|
segments.add(ns.field / ns.value)
|
||||||
|
|
||||||
# is it problematic that per this logic Key(/a:b) evaluates to the same path
|
self.root / segments.joinPath()
|
||||||
# as Key(/a/b)? may need to check if/how other Datastore implementations
|
|
||||||
# distinguish them
|
|
||||||
|
|
||||||
self.root / joinPath(segments)
|
template checkProtected*(path: string): bool =
|
||||||
|
path in ProtectedPaths
|
||||||
|
|
||||||
|
template allowed*(path: string): bool =
|
||||||
|
var notfound = true
|
||||||
|
for s in path:
|
||||||
|
if s.char notin Allowed:
|
||||||
|
notfound = false
|
||||||
|
break
|
||||||
|
|
||||||
|
notfound
|
||||||
|
|
||||||
|
template validDepth*(self: FSDatastore, key: Key): bool =
|
||||||
|
key.len <= self.depth
|
||||||
|
|
||||||
method contains*(self: FSDatastore, key: Key): Future[?!bool] {.async.} =
|
method contains*(self: FSDatastore, key: Key): Future[?!bool] {.async.} =
|
||||||
return success fileExists(self.path(key))
|
|
||||||
|
|
||||||
method delete*(self: FSDatastore, key: Key): Future[?!void] {.async.} =
|
if not self.validDepth(key):
|
||||||
|
return failure "Path has invalid depth!"
|
||||||
|
|
||||||
let
|
let
|
||||||
path = self.path(key)
|
path = self.path(key)
|
||||||
|
|
||||||
|
if not path.allowed:
|
||||||
|
return failure "Path is contains invalid characters!"
|
||||||
|
|
||||||
|
if checkProtected(path):
|
||||||
|
return failure "Path is protected!"
|
||||||
|
|
||||||
|
return success fileExists(path)
|
||||||
|
|
||||||
|
method delete*(self: FSDatastore, key: Key): Future[?!void] {.async.} =
|
||||||
|
|
||||||
|
if not self.validDepth(key):
|
||||||
|
return failure "Path has invalid depth!"
|
||||||
|
|
||||||
|
let
|
||||||
|
path = self.path(key)
|
||||||
|
|
||||||
|
if not path.allowed:
|
||||||
|
return failure "Path is contains invalid characters!"
|
||||||
|
|
||||||
if checkProtected(path):
|
if checkProtected(path):
|
||||||
return failure "Path is protected!"
|
return failure "Path is protected!"
|
||||||
|
|
||||||
@ -84,9 +120,15 @@ method get*(self: FSDatastore, key: Key): Future[?!seq[byte]] {.async.} =
|
|||||||
# calling the former after allocating a seq with size automatically
|
# calling the former after allocating a seq with size automatically
|
||||||
# determined via `getFileSize`
|
# determined via `getFileSize`
|
||||||
|
|
||||||
|
if not self.validDepth(key):
|
||||||
|
return failure "Path has invalid depth!"
|
||||||
|
|
||||||
let
|
let
|
||||||
path = self.path(key)
|
path = self.path(key)
|
||||||
|
|
||||||
|
if not path.allowed:
|
||||||
|
return failure "Path is contains invalid characters!"
|
||||||
|
|
||||||
if checkProtected(path):
|
if checkProtected(path):
|
||||||
return failure "Path is protected!"
|
return failure "Path is protected!"
|
||||||
|
|
||||||
@ -119,7 +161,7 @@ method get*(self: FSDatastore, key: Key): Future[?!seq[byte]] {.async.} =
|
|||||||
|
|
||||||
return success bytes
|
return success bytes
|
||||||
|
|
||||||
except IOError as e:
|
except CatchableError as e:
|
||||||
return failure e
|
return failure e
|
||||||
|
|
||||||
method put*(
|
method put*(
|
||||||
@ -127,18 +169,22 @@ method put*(
|
|||||||
key: Key,
|
key: Key,
|
||||||
data: seq[byte]): Future[?!void] {.async, locks: "unknown".} =
|
data: seq[byte]): Future[?!void] {.async, locks: "unknown".} =
|
||||||
|
|
||||||
|
if not self.validDepth(key):
|
||||||
|
return failure "Path has invalid depth!"
|
||||||
|
|
||||||
let
|
let
|
||||||
path = self.path(key)
|
path = self.path(key)
|
||||||
|
|
||||||
|
if not path.allowed:
|
||||||
|
return failure "Path is contains invalid characters!"
|
||||||
|
|
||||||
if checkProtected(path):
|
if checkProtected(path):
|
||||||
return failure "Path is protected!"
|
return failure "Path is protected!"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
createDir(parentDir(path))
|
createDir(parentDir(path))
|
||||||
writeFile(path, data)
|
writeFile(path, data)
|
||||||
except IOError as e:
|
except CatchableError as e:
|
||||||
return failure e
|
|
||||||
except OSError as e:
|
|
||||||
return failure e
|
return failure e
|
||||||
|
|
||||||
return success()
|
return success()
|
||||||
@ -152,6 +198,7 @@ method put*(
|
|||||||
proc new*(
|
proc new*(
|
||||||
T: type FSDatastore,
|
T: type FSDatastore,
|
||||||
root: string,
|
root: string,
|
||||||
|
depth = 2,
|
||||||
caseSensitive = true,
|
caseSensitive = true,
|
||||||
ignoreProtected = false): ?!T =
|
ignoreProtected = false): ?!T =
|
||||||
|
|
||||||
@ -165,4 +212,5 @@ proc new*(
|
|||||||
|
|
||||||
success T(
|
success T(
|
||||||
root: root,
|
root: root,
|
||||||
ignoreProtected: ignoreProtected)
|
ignoreProtected: ignoreProtected,
|
||||||
|
depth: depth)
|
||||||
Loading…
x
Reference in New Issue
Block a user