add iam system

add iam store

feat: add crypto crate

introduce decrypt_data and encrypt_data functions

Signed-off-by: bestgopher <84328409@qq.com>
This commit is contained in:
bestgopher
2024-10-14 23:11:49 +08:00
parent 8519a596ec
commit bb2f765e5d
61 changed files with 5319 additions and 64 deletions
+141
View File
@@ -0,0 +1,141 @@
use std::{fmt::Write, usize};
struct LazyBuf<'a> {
s: &'a str,
buf: Option<Vec<u8>>,
w: usize,
}
impl<'a> LazyBuf<'a> {
pub fn new(s: &'a str) -> Self {
Self { s, buf: None, w: 0 }
}
fn index(&self, i: usize) -> u8 {
self.buf.as_ref().map(|x| x[i]).unwrap_or_else(|| self.s.as_bytes()[i])
}
fn append(&mut self, c: u8) {
if self.buf.is_none() {
if self.w < self.s.len() && self.s.as_bytes()[self.w] == c {
self.w += 1;
return;
}
self.buf = Some({
let mut buf = vec![0u8; self.s.len()];
buf[..self.w].copy_from_slice(&self.s.as_bytes()[..self.w]);
buf
});
}
self.buf.as_mut().unwrap()[self.w] = c;
self.w += 1;
}
fn string(&self) -> String {
match self.buf {
Some(ref s) => String::from_utf8_lossy(&s[..self.w]).to_string(),
None => String::from_utf8_lossy(&self.s.as_bytes()[..self.w]).to_string(),
}
}
}
/// copy from golang(path.Clean)
pub fn clean(path: &str) -> String {
if path.is_empty() {
return ".".into();
}
let p = path.as_bytes();
let (rooted, n, mut out, mut r, mut dotdot) = (p[0] == b'/', path.len(), LazyBuf::new(path), 0, 0);
if rooted {
out.append(b'/');
r = 1;
dotdot = 1;
}
while r < n {
if p[r] == b'/' || (p[r] == b'.' && (r + 1 == n || p[r + 1] == b'/')) {
r += 1;
} else if p[r] == b'.' && p[r + 1] == b'.' && (r + 2 == n || p[r + 2] == b'/') {
r += 2;
if out.w > dotdot {
out.w -= 1;
while out.w > dotdot && out.index(out.w) != b'/' {
out.w -= 1;
}
} else if !rooted {
if out.w > 0 {
out.append(b'/');
}
out.append(b'.');
out.append(b'.');
dotdot = out.w;
}
} else {
if rooted && out.w != 1 || !rooted && out.w != 0 {
out.append(b'/');
}
while r < n && p[r] != b'/' {
out.append(p[r]);
r += 1;
}
}
}
if out.w == 0 {
".".into()
} else {
out.string()
}
}
#[cfg(test)]
mod tests {
use super::clean;
#[test_case::test_case("", "."; "1")]
#[test_case::test_case("abc", "abc"; "2")]
#[test_case::test_case("abc/def", "abc/def"; "3")]
#[test_case::test_case("a/b/c", "a/b/c"; "4")]
#[test_case::test_case(".", "."; "5")]
#[test_case::test_case("..", ".."; "6")]
#[test_case::test_case("../..", "../.."; "7")]
#[test_case::test_case("../../abc", "../../abc"; "8")]
#[test_case::test_case("/abc", "/abc"; "9")]
#[test_case::test_case("/", "/"; "10")]
#[test_case::test_case("abc/", "abc"; "11")]
#[test_case::test_case("abc/def/", "abc/def"; "12")]
#[test_case::test_case("a/b/c/", "a/b/c"; "13")]
#[test_case::test_case("./", "."; "14")]
#[test_case::test_case("../", ".."; "15")]
#[test_case::test_case("../../", "../.."; "16")]
#[test_case::test_case("/abc/", "/abc"; "17")]
#[test_case::test_case("abc//def//ghi", "abc/def/ghi"; "18")]
#[test_case::test_case("//abc", "/abc"; "19")]
#[test_case::test_case("///abc", "/abc"; "20")]
#[test_case::test_case("//abc//", "/abc"; "21")]
#[test_case::test_case("abc//", "abc"; "22")]
#[test_case::test_case("abc/./def", "abc/def"; "23")]
#[test_case::test_case("/./abc/def", "/abc/def"; "24")]
#[test_case::test_case("abc/.", "abc"; "25")]
#[test_case::test_case("abc/def/ghi/../jkl", "abc/def/jkl"; "26")]
#[test_case::test_case("abc/def/../ghi/../jkl", "abc/jkl"; "27")]
#[test_case::test_case("abc/def/..", "abc"; "28")]
#[test_case::test_case("abc/def/../..", "."; "29")]
#[test_case::test_case("/abc/def/../..", "/"; "30")]
#[test_case::test_case("abc/def/../../..", ".."; "31")]
#[test_case::test_case("/abc/def/../../..", "/"; "32")]
#[test_case::test_case("abc/def/../../../ghi/jkl/../../../mno", "../../mno"; "33")]
#[test_case::test_case("abc/./../def", "def"; "34")]
#[test_case::test_case("abc//./../def", "def"; "35")]
#[test_case::test_case("abc/../../././../def", "../../def"; "36")]
fn test_clean(path: &str, result: &str) {
assert_eq!(clean(path), result.to_owned());
assert_eq!(clean(result), result.to_owned());
}
}
+189
View File
@@ -0,0 +1,189 @@
pub fn is_simple_match<P, N>(pattern: P, name: N) -> bool
where
P: AsRef<str>,
N: AsRef<str>,
{
inner_match(pattern, name, true)
}
pub fn is_match<P, N>(pattern: P, name: N) -> bool
where
P: AsRef<str>,
N: AsRef<str>,
{
inner_match(pattern, name, false)
}
pub fn is_match_as_pattern_prefix<P, N>(pattern: P, text: N) -> bool
where
P: AsRef<str>,
N: AsRef<str>,
{
let (mut p, mut t) = (pattern.as_ref().as_bytes().into_iter(), text.as_ref().as_bytes().into_iter());
while let (Some(&x), Some(&y)) = (p.next(), t.next()) {
if x == b'*' {
return true;
}
if x == b'?' {
continue;
}
if x != y {
return false;
}
}
text.as_ref().len() <= pattern.as_ref().len()
}
fn inner_match(pattern: impl AsRef<str>, name: impl AsRef<str>, simple: bool) -> bool {
let (pattern, name) = (pattern.as_ref(), name.as_ref());
if pattern.is_empty() {
return pattern == name;
}
if pattern == "*" {
return true;
}
deep_match(name.as_bytes(), pattern.as_bytes(), simple)
}
fn deep_match(mut name: &[u8], mut pattern: &[u8], simple: bool) -> bool {
while !pattern.is_empty() {
match pattern[0] {
b'?' => {
if name.is_empty() {
return simple;
}
}
b'*' => {
return pattern.len() == 1
|| deep_match(name, &pattern[1..], simple)
|| (!name.is_empty() && deep_match(&name[1..], pattern, simple));
}
_ => {
if name.is_empty() || name[0] != pattern[0] {
return false;
}
}
}
name = &name[1..];
pattern = &pattern[1..];
}
name.is_empty() && pattern.is_empty()
}
#[cfg(test)]
mod tests {
use super::{is_match, is_match_as_pattern_prefix, is_simple_match};
#[test_case::test_case("*", "s3:GetObject" => true ; "1")]
#[test_case::test_case("", "s3:GetObject" => false ; "2")]
#[test_case::test_case("", "" => true; "3")]
#[test_case::test_case("s3:*", "s3:ListMultipartUploadParts" => true; "4")]
#[test_case::test_case("s3:ListBucketMultipartUploads", "s3:ListBucket" => false; "5")]
#[test_case::test_case("s3:ListBucket", "s3:ListBucket" => true; "6")]
#[test_case::test_case("s3:ListBucketMultipartUploads", "s3:ListBucketMultipartUploads" => true; "7")]
#[test_case::test_case("my-bucket/oo*", "my-bucket/oo" => true; "8")]
#[test_case::test_case("my-bucket/In*", "my-bucket/India/Karnataka/" => true; "9")]
#[test_case::test_case("my-bucket/In*", "my-bucket/Karnataka/India/" => false; "10")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Ban" => true; "11")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Ban/Ban/Ban/Ban/Ban" => true; "12")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Area1/Area2/Area3/Ban" => true; "13")]
#[test_case::test_case( "my-bucket/In*/Ka*/Ba", "my-bucket/India/State1/State2/Karnataka/Area1/Area2/Area3/Ban" => ignore["will fail"] true; "14")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Bangalore" => false; "15")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban*", "my-bucket/India/Karnataka/Bangalore" => true; "16")]
#[test_case::test_case("my-bucket/*", "my-bucket/India" => true; "17")]
#[test_case::test_case("my-bucket/oo*", "my-bucket/odo" => false; "18")]
#[test_case::test_case("my-bucket?/abc*", "mybucket/abc" => false; "19")]
#[test_case::test_case("my-bucket?/abc*", "my-bucket1/abc" => true; "20")]
#[test_case::test_case("my-?-bucket/abc*", "my--bucket/abc" => false; "21")]
#[test_case::test_case("my-?-bucket/abc*", "my-1-bucket/abc" => true; "22")]
#[test_case::test_case("my-?-bucket/abc*", "my-k-bucket/abc" => true; "23")]
#[test_case::test_case("my??bucket/abc*", "mybucket/abc" => false; "24")]
#[test_case::test_case("my??bucket/abc*", "my4abucket/abc" => true; "25")]
#[test_case::test_case("my-bucket?abc*", "my-bucket/abc" => true; "26")]
#[test_case::test_case("my-bucket/abc?efg", "my-bucket/abcdefg" => true; "27")]
#[test_case::test_case("my-bucket/abc?efg", "my-bucket/abc/efg" => true; "28")]
#[test_case::test_case("my-bucket/abc????", "my-bucket/abcde" => false; "29")]
#[test_case::test_case("my-bucket/abc????", "my-bucket/abcdefg" => true; "30")]
#[test_case::test_case("my-bucket/abc?", "my-bucket/abc" => false; "31")]
#[test_case::test_case("my-bucket/abc?", "my-bucket/abcd" => true; "32")]
#[test_case::test_case("my-bucket/abc?", "my-bucket/abcde" => false; "33")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mnop" => false; "34")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mnopqrst/mnopqr" => true; "35")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mnopqrst/mnopqrs" => true; "36")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mnop" => false; "37")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mnopq" => true; "38")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mnopqr" => true; "39")]
#[test_case::test_case("my-bucket/mnop*?and", "my-bucket/mnopqand" => true; "40")]
#[test_case::test_case("my-bucket/mnop*?and", "my-bucket/mnopand" => false; "41")]
#[test_case::test_case("my-bucket/mnop*?and", "my-bucket/mnopqand" => true; "42")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mn" => false; "43")]
#[test_case::test_case("my-bucket/mnop*?", "my-bucket/mnopqrst/mnopqrs" => true; "44")]
#[test_case::test_case("my-bucket/mnop*??", "my-bucket/mnopqrst" => true; "45")]
#[test_case::test_case("my-bucket/mnop*qrst", "my-bucket/mnopabcdegqrst" => true; "46")]
#[test_case::test_case("my-bucket/mnop*?and", "my-bucket/mnopqand" => true; "47")]
#[test_case::test_case("my-bucket/mnop*?and", "my-bucket/mnopand" => false; "48")]
#[test_case::test_case("my-bucket/mnop*?and?", "my-bucket/mnopqanda" => true; "49")]
#[test_case::test_case("my-bucket/mnop*?and", "my-bucket/mnopqanda" => false; "50")]
#[test_case::test_case("my-?-bucket/abc*", "my-bucket/mnopqanda" => false; "51")]
#[test_case::test_case("a?", "a" => false; "52")]
fn test_is_match(pattern: &str, text: &str) -> bool {
is_match(pattern, text)
}
#[test_case::test_case("*", "s3:GetObject" => true ; "1")]
#[test_case::test_case("", "s3:GetObject" => false ; "2")]
#[test_case::test_case("", "" => true ; "3")]
#[test_case::test_case("s3:*", "s3:ListMultipartUploadParts" => true ; "4")]
#[test_case::test_case("s3:ListBucketMultipartUploads", "s3:ListBucket" => false ; "5")]
#[test_case::test_case("s3:ListBucket", "s3:ListBucket" => true ; "6")]
#[test_case::test_case("s3:ListBucketMultipartUploads", "s3:ListBucketMultipartUploads" => true ; "7")]
#[test_case::test_case("my-bucket/oo*", "my-bucket/oo" => true ; "8")]
#[test_case::test_case("my-bucket/In*", "my-bucket/India/Karnataka/" => true ; "9")]
#[test_case::test_case("my-bucket/In*", "my-bucket/Karnataka/India/" => false ; "10")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Ban" => true ; "11")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Ban/Ban/Ban/Ban/Ban" => true ; "12")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Area1/Area2/Area3/Ban" => true ; "13")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/State1/State2/Karnataka/Area1/Area2/Area3/Ban" => true ; "14")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban", "my-bucket/India/Karnataka/Bangalore" => false ; "15")]
#[test_case::test_case("my-bucket/In*/Ka*/Ban*", "my-bucket/India/Karnataka/Bangalore" => true ; "16")]
#[test_case::test_case("my-bucket/*", "my-bucket/India" => true ; "17")]
#[test_case::test_case("my-bucket/oo*", "my-bucket/odo" => false ; "18")]
#[test_case::test_case("my-bucket/oo?*", "my-bucket/oo???" => true ; "19")]
#[test_case::test_case("my-bucket/oo??*", "my-bucket/odo" => false ; "20")]
#[test_case::test_case("?h?*", "?h?hello" => true ; "21")]
#[test_case::test_case("a?", "a" => true ; "22")]
fn test_is_simple_match(pattern: &str, text: &str) -> bool {
is_simple_match(pattern, text)
}
#[test_case::test_case("", "" => true ; "1")]
#[test_case::test_case("a", "" => true ; "2")]
#[test_case::test_case("a", "b" => false ; "3")]
#[test_case::test_case("abc", "ab" => true ; "4")]
#[test_case::test_case("ab*", "ab" => true ; "5")]
#[test_case::test_case("abc*", "ab" => true ; "6")]
#[test_case::test_case("abc?", "ab" => true ; "7")]
#[test_case::test_case("abc*", "abd" => false ; "8")]
#[test_case::test_case("abc*c", "abcd" => true ; "9")]
#[test_case::test_case("ab*??d", "abxxc" => true ; "10")]
#[test_case::test_case("ab*??", "abxc" => true ; "11")]
#[test_case::test_case("ab??", "abxc" => true ; "12")]
#[test_case::test_case("ab??", "abx" => true ; "13")]
#[test_case::test_case("ab??d", "abcxd" => true ; "14")]
#[test_case::test_case("ab??d", "abcxdd" => false ; "15")]
#[test_case::test_case("", "b" => false ; "16")]
fn test_is_match_as_pattern_prefix(pattern: &str, text: &str) -> bool {
is_match_as_pattern_prefix(pattern, text)
}
}