implements trail sharing

This commit is contained in:
Christian Beutel
2024-06-06 02:02:23 +02:00
parent 5d46ad96b4
commit ad5a4e668b
44 changed files with 1257 additions and 308 deletions

View File

@@ -13,7 +13,6 @@ require (
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go v1.51.11 // indirect
github.com/aws/aws-sdk-go-v2 v1.26.1 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.10 // indirect
@@ -45,7 +44,6 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/google/wire v0.6.0 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
@@ -70,7 +68,6 @@ require (
gocloud.dev v0.37.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/image v0.15.0 // indirect
golang.org/x/mod v0.16.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sync v0.6.0 // indirect
@@ -78,21 +75,16 @@ require (
golang.org/x/term v0.18.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.19.0 // indirect
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
google.golang.org/api v0.172.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa // indirect
google.golang.org/grpc v1.62.1 // indirect
google.golang.org/protobuf v1.33.0 // indirect
lukechampine.com/uint128 v1.3.0 // indirect
modernc.org/cc/v3 v3.41.0 // indirect
modernc.org/ccgo/v3 v3.16.15 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.49.0 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect
modernc.org/opt v0.1.3 // indirect
modernc.org/sqlite v1.29.5 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect

188
db/go.sum
View File

@@ -1,14 +1,16 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y=
cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic=
cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk=
cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI=
cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM=
cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4=
cloud.google.com/go/compute v1.25.0 h1:H1/4SqSUhjPFE7L5ddzHOfY2bCAvjwNRZPNl6Ni5oYU=
cloud.google.com/go/compute v1.25.0/go.mod h1:GR7F0ZPZH8EhChlMo9FkLd7eUTwEymjqQagxzilIxIE=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI=
cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8=
cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w=
cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8=
cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc=
cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI=
cloud.google.com/go/storage v1.39.1 h1:MvraqHKhogCOTXTlct/9C3K3+Uy2jBmFYb3/Sp6dVtY=
cloud.google.com/go/storage v1.39.1/go.mod h1:xK6xZmxZmo+fyP7+DEF6FhNc24/JAe95OLyOHCXFH1o=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ=
github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -19,83 +21,44 @@ github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/aws/aws-sdk-go v1.50.2 h1:/vS+Uhv2FPcqcTxBmgT3tvvN5q6pMAKu6QXltgXlGgo=
github.com/aws/aws-sdk-go v1.50.2/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go v1.51.11 h1:El5VypsMIz7sFwAAj/j06JX9UGs4KAbAIEaZ57bNY4s=
github.com/aws/aws-sdk-go v1.51.11/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
github.com/aws/aws-sdk-go-v2 v1.24.1 h1:xAojnj+ktS95YZlDf0zxWBkbFtymPeDP+rvUQIH3uAU=
github.com/aws/aws-sdk-go-v2 v1.24.1/go.mod h1:LNh45Br1YAkEKaAqvmE1m8FUx6a5b/V0oAKV7of29b4=
github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA=
github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4 h1:OCs21ST2LrepDfD3lwlQiOqIGp6JiEUqG84GzTDoyJs=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.5.4/go.mod h1:usURWEKSNNAcAZuzRn/9ZYPT8aZQkR7xcCtunK/LkJo=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg=
github.com/aws/aws-sdk-go-v2/config v1.26.6 h1:Z/7w9bUqlRI0FFQpetVuFYEsjzE3h7fpU6HuGmfPL/o=
github.com/aws/aws-sdk-go-v2/config v1.26.6/go.mod h1:uKU6cnDmYCvJ+pxO9S4cWDb2yWWIH5hra+32hVh1MI4=
github.com/aws/aws-sdk-go-v2/config v1.27.10 h1:PS+65jThT0T/snC5WjyfHHyUgG+eBoupSDV+f838cro=
github.com/aws/aws-sdk-go-v2/config v1.27.10/go.mod h1:BePM7Vo4OBpHreKRUMuDXX+/+JWP38FLkzl5m27/Jjs=
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 h1:8q6Rliyv0aUFAVtzaldUEcS+T5gbadPbWdV1WcAddK8=
github.com/aws/aws-sdk-go-v2/credentials v1.16.16/go.mod h1:UHVZrdUsv63hPXFo1H7c5fEneoVo9UXiz36QG1GEPi0=
github.com/aws/aws-sdk-go-v2/credentials v1.17.10 h1:qDZ3EA2lv1KangvQB6y258OssCHD0xvaGiEDkG4X/10=
github.com/aws/aws-sdk-go-v2/credentials v1.17.10/go.mod h1:6t3sucOaYDwDssHQa0ojH1RpmVmF5/jArkye1b2FKMI=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11 h1:c5I5iH+DZcH3xOIMlz3/tCKJDaHFwYEmxvlh2fAcFo8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.14.11/go.mod h1:cRrYDYAMUohBJUtUnOhydaMHtiK/1NZ0Otc9lIb6O0Y=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.14 h1:ogP1WgyvN/qxPJkgtFMD7G2eKb5p/61Jomx+nIHXUQ4=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.15.14/go.mod h1:nYd/WmIrXlBHW/5QwrZP81/Gz08wKi87nV6EI1kmqx4=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.14 h1:Nhcq+ODoD9FRQYI3lATy6iADS5maER3ZXSfE8v3FMh8=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.14/go.mod h1:VlBbwTpgCj3rKWMVkEAYiAR3FKs7Mi3jALTMGfbfuns=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 h1:vF+Zgd9s+H4vOXd5BMaPWykta2a6Ih0AKLq/X6NYKn4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10/go.mod h1:6BkRjejp/GR4411UGqkX8+wFMbFbqsUIimfK4XjOKR4=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 h1:nYPe006ktcqUji8S2mqXf9c/7NdiKriOwMvWQHgYztw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10/go.mod h1:6UV4SZkVvmODfXKql4LCbaZUpF7HO2BX38FgBf9ZOLw=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3 h1:n3GDfwqF2tzEkXlv5cuy4iy7LpKDtqDMcNLfZDu9rls=
github.com/aws/aws-sdk-go-v2/internal/ini v1.7.3/go.mod h1:6fQQgfuGmw8Al/3M2IgIllycxV7ZW7WCdVSqfBeUiCY=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10 h1:5oE2WzJE56/mVveuDZPJESKlg/00AaS2pY2QZcnxg4M=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.2.10/go.mod h1:FHbKWQtRBYUz4vO5WBWjzMD2by126ny5y/1EoaWoLfI=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5 h1:81KE7vaZzrl7yHBYHVEzYB8sypz11NMOZ40YlWvPxsU=
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.5/go.mod h1:LIt2rg7Mcgn09Ygbdh/RdIm0rQ+3BNkbP1gyVMFtRK0=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4 h1:/b31bi3YVNlkzkBrm9LfpaKoaYZUxIAj4sHfOTmLfqw=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.10.4/go.mod h1:2aGXHFmbInwgP9ZfpmdIfOELL79zhdNYNmReK8qDfdQ=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10 h1:L0ai8WICYHozIKK+OtPzVJBugL7culcuM4E4JOpIEm8=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.2.10/go.mod h1:byqfyxJBshFk0fF9YmK0M0ugIO8OWjzH2T3bPG4eGuA=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7 h1:ZMeFZ5yk+Ek+jNr1+uwCd2tG89t6oTS5yVWpa6yy2es=
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.7/go.mod h1:mxV05U+4JiHqIpGqqYXOHLPKUC6bDXC44bsUhNjOEwY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10 h1:DBYTXwIGQSGs9w4jKm60F5dmCQ3EEruxdc0MFh+3EY4=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.10.10/go.mod h1:wohMUQiFdzo0NtxbBg0mSRGZ4vL3n0dKjLTINdcIino=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10 h1:KOxnQeWy5sXyS37fdKEvAsGHOr9fa/qvwxfJurR/BzE=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.16.10/go.mod h1:jMx5INQFYFYB3lQD9W0D8Ohgq6Wnl7NYOJ2TQndbulI=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5 h1:f9RyWNtS8oH7cZlbn+/JNPpjUk5+5fLd5lM9M0i49Ys=
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.5/go.mod h1:h5CoMZV2VF297/VLhRhO1WF+XYWOzXo+4HsObA4HjBQ=
github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0 h1:PJTdBMsyvra6FtED7JZtDpQrIAflYDHFoZAu/sKYkwU=
github.com/aws/aws-sdk-go-v2/service/s3 v1.48.0/go.mod h1:4qXHrG1Ne3VGIMZPCB8OjH/pLFO94sKABIusjh0KWPU=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1 h1:6cnno47Me9bRykw9AEv9zkXE+5or7jz8TsskTTccbgc=
github.com/aws/aws-sdk-go-v2/service/s3 v1.53.1/go.mod h1:qmdkIIAC+GCLASF7R2whgNrJADz0QZPX+Seiw/i4S3o=
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7 h1:eajuO3nykDPdYicLlP3AGgOyVN3MOlFmZv7WGTuJPow=
github.com/aws/aws-sdk-go-v2/service/sso v1.18.7/go.mod h1:+mJNDdF+qiUlNKNC3fxn74WWNN+sOiGOEImje+3ScPM=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4 h1:WzFol5Cd+yDxPAdnzTA5LmpHYSWinhmSj4rQChV0ee8=
github.com/aws/aws-sdk-go-v2/service/sso v1.20.4/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7 h1:QPMJf+Jw8E1l7zqhZmMlFw6w1NmfkfiSK8mS4zOx3BA=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.21.7/go.mod h1:ykf3COxYI0UJmxcfcxcVuz7b6uADi1FkiUz6Eb7AgM8=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE=
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7 h1:NzO4Vrau795RkUdSHKEwiR01FaGzGOH1EETJ+5QHnm0=
github.com/aws/aws-sdk-go-v2/service/sts v1.26.7/go.mod h1:6h2YuIoxaMSCFf5fi1EgZAwdfkGMgDY+DVfa61uLe4U=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU=
github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw=
github.com/aws/smithy-go v1.19.0 h1:KWFKQV80DpP3vJrrA9sVAHQ5gc2z8i4EzrLhLlWXcBM=
github.com/aws/smithy-go v1.19.0/go.mod h1:NukqUGpCZIILqqiV0NIjeFh24kd/FAa4beRb6nbIUPE=
github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q=
github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
@@ -127,15 +90,15 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/ganigeorgiev/fexpr v0.4.0 h1:ojitI+VMNZX/odeNL1x3RzTTE8qAIVvnSSYPNAnQFDI=
github.com/ganigeorgiev/fexpr v0.4.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es=
github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.0 h1:UtktXaU2Nb64z/pLiGIxY4431SJ4/dR5cjMmlVHgnT4=
github.com/go-sql-driver/mysql v1.8.0/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
@@ -157,8 +120,6 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -170,28 +131,17 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE=
github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk=
github.com/google/go-replayers/httpreplay v1.2.0 h1:VM1wEyyjaoU53BwrOnaf9VhAyQQEEioJvFYxYcLRKzk=
github.com/google/go-replayers/httpreplay v1.2.0/go.mod h1:WahEFFZZ7a1P4VM1qEeHy+tME4bwyqPcwWbNlUI1Mcg=
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
github.com/googleapis/gax-go/v2 v2.12.3 h1:5/zPPDvw8Q1SuXjrqrZslrqT7dL/uJT2CQii/cLCKqA=
github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBHwWRvkNFJUQcS4=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
@@ -226,8 +176,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/meilisearch/meilisearch-go v0.26.2 h1:3gTlmiV1dHHumVUhYdJbvh3camiNiyqQ1hNveVsU2OE=
@@ -241,8 +189,6 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pocketbase/dbx v1.10.1 h1:cw+vsyfCJD8YObOVeqb93YErnlxwYMkNZ4rwN0G0AaA=
github.com/pocketbase/dbx v1.10.1/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
github.com/pocketbase/pocketbase v0.21.3 h1:pXNXYi1Ff/zt47DOASYbD6XCOYlqBqJVTgCWPHCQ++s=
github.com/pocketbase/pocketbase v0.21.3/go.mod h1:V3/y5RJFddyN0I+/cmMboKq5Tv3UHpTuM+R8/Qo39OU=
github.com/pocketbase/pocketbase v0.22.7 h1:/XVqNchyC6Lkho9R6Av3Lh0RGKnkFreH5BGHdaDcbaY=
github.com/pocketbase/pocketbase v0.22.7/go.mod h1:B4iOkmkV8z78DvHKFplar0+CQAaUo2/wJaOqiGHzXSE=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -277,27 +223,22 @@ github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7Fw
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo=
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
gocloud.dev v0.36.0 h1:q5zoXux4xkOZP473e1EZbG8Gq9f0vlg1VNH5Du/ybus=
gocloud.dev v0.36.0/go.mod h1:bLxah6JQVKBaIxzsr5BQLYB4IYdWHkMZdzCXlo6F0gg=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
gocloud.dev v0.37.0 h1:XF1rN6R0qZI/9DYjN16Uy0durAmSlf58DHOcb28GPro=
gocloud.dev v0.37.0/go.mod h1:7/O4kqdInCNsc6LqgmuFnS0GRew4XNNYWpA44yQnwco=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -308,10 +249,7 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -325,24 +263,15 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -358,21 +287,11 @@ golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8=
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -382,9 +301,6 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
@@ -393,21 +309,15 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
google.golang.org/api v0.157.0 h1:ORAeqmbrrozeyw5NjnMxh7peHO0UzV4wWYSwZeCUb20=
google.golang.org/api v0.157.0/go.mod h1:+z4v4ufbZ1WEpld6yMGHyggs+PmAHiaLNj5ytP3N01g=
google.golang.org/api v0.172.0 h1:/1OcMZGPmW1rX2LCu2CmGUD1KXK1+pfzxotxyRUCCdk=
google.golang.org/api v0.172.0/go.mod h1:+fJZq6QXWfa9pXhnIzsjx4yI22d4aI9ZpLb58gvXjis=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
@@ -418,12 +328,10 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac h1:ZL/Teoy/ZGnzyrqK/Optxxp2pmVh+fmJ97slxSRyzUg=
google.golang.org/genproto v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:+Rvu7ElI+aLzyDQhpHMFMMltsD6m7nqpuWDd2CwJw3k=
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM=
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7 h1:ImUcDPHjTrAqNhlOkSocDLfG9rrNHH7w7uoKWPaWZ8s=
google.golang.org/genproto v0.0.0-20240311173647-c811ad7063a7/go.mod h1:/3XmxOjePkvmKrHuBy4zNFw7IzxJXtAgdpXi8Ll990U=
google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7 h1:oqta3O3AnlWbmIE3bFnWbu4bRxZjfbWCp0cKSuZh01E=
google.golang.org/genproto/googleapis/api v0.0.0-20240311173647-c811ad7063a7/go.mod h1:VQW3tUculP/D4B+xVCo+VgSq8As6wA9ZjHl//pmk+6s=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa h1:RBgMaUMP+6soRkik4VoN8ojR2nex2TqZwjSSogic+eo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -431,8 +339,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0=
google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs=
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -446,8 +352,6 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -459,20 +363,16 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q=
modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y=
modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0=
modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI=
modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/cc/v4 v4.19.5 h1:QlsZyQ1zf78DGeqnQ9ILi9hXyMdoC5e1qoGNUyBjHQw=
modernc.org/cc/v4 v4.19.5/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.13.1 h1:qBttaSxEHNze36VBivw1/vkHuyjMDN3RY5wQX+p1Oxg=
modernc.org/ccgo/v4 v4.13.1/go.mod h1:Td6RI9W9G2ZpKHaJ7UeGEiB2aIpoDqLBnm4wtkbJTbQ=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v1.40.7 h1:oeLS0G067ZqUu+v143Dqad0btMfKmNS7SuOsnkq0Ysg=
modernc.org/libc v1.40.7/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
modernc.org/libc v1.49.0 h1:/kkNBuCXvlTbOGwrQdgR67eK1Y9+kR+fhdBd89C64VM=
modernc.org/libc v1.49.0/go.mod h1:DNz0lgQgT6FPIPm8rHtjFj0FL5/YOr/NYFXWYBcSxMw=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
@@ -481,15 +381,11 @@ modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ=
modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.29.5 h1:8l/SQKAjDtZFo9lkJLdk8g9JEOeYRG4/ghStDCCTiTE=
modernc.org/sqlite v1.29.5/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE=

View File

@@ -8,6 +8,7 @@ import (
"github.com/labstack/echo/v5"
"github.com/meilisearch/meilisearch-go"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/forms"
@@ -16,6 +17,7 @@ import (
"github.com/pocketbase/pocketbase/tools/filesystem"
_ "pocketbase/migrations"
"pocketbase/util"
)
func main() {
@@ -38,11 +40,11 @@ func main() {
searchRules := map[string]interface{}{
"cities500": map[string]string{},
"trails": map[string]string{
"filter": "public = true OR author = " + userId,
"filter": "public = true OR author = " + userId + " OR shares = " + userId,
},
}
if token, err := generateMeilisearchToken(searchRules, client); err != nil {
if token, err := util.GenerateMeilisearchToken(searchRules, client); err != nil {
return err
} else {
record.Set("token", token)
@@ -56,14 +58,14 @@ func main() {
})
app.OnRecordAfterCreateRequest("trails").Add(func(e *core.RecordCreateEvent) error {
if err := indexRecord(e.Record, client); err != nil {
if err := util.IndexTrail(e.Record, client); err != nil {
return err
}
return nil
})
app.OnRecordAfterUpdateRequest("trails").Add(func(e *core.RecordUpdateEvent) error {
if err := indexRecord(e.Record, client); err != nil {
if err := util.UpdateTrail(e.Record, client); err != nil {
return err
}
return nil
@@ -76,6 +78,34 @@ func main() {
return nil
})
app.OnRecordAfterCreateRequest("trail_share").Add(func(e *core.RecordCreateEvent) error {
trailId := e.Record.GetString("trail")
shares, err := app.Dao().FindRecordsByExpr("trail_share",
dbx.NewExp("trail = {:trailId}", dbx.Params{"trailId": trailId}),
)
if err != nil {
return err
}
userIds := []string{}
for _, r := range shares {
userIds = append(userIds, r.GetString("user"))
}
if err := util.UpdateTrailShares(trailId, userIds, client); err != nil {
return err
}
return nil
})
app.OnRecordAfterDeleteRequest("trail_share").Add(func(e *core.RecordDeleteEvent) error {
trailId := e.Record.GetString("trail")
if err := util.UpdateTrailShares(trailId, []string{}, client); err != nil {
return err
}
return nil
})
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
e.Router.GET("/public/search/token", func(c echo.Context) error {
searchRules := map[string]interface{}{
@@ -85,7 +115,7 @@ func main() {
},
}
if token, err := generateMeilisearchToken(searchRules, client); err != nil {
if token, err := util.GenerateMeilisearchToken(searchRules, client); err != nil {
return err
} else {
return c.JSON(http.StatusOK, map[string]string{"token": token})
@@ -127,7 +157,7 @@ func main() {
for _, trail := range trails {
log.Println(trail)
if err := indexRecord(trail, client); err != nil {
if err := util.IndexTrail(trail, client); err != nil {
return err
}
}

View File

@@ -1,66 +0,0 @@
package main
import (
"errors"
"log"
"github.com/meilisearch/meilisearch-go"
"github.com/pocketbase/pocketbase/models"
)
func indexRecord(r *models.Record, client *meilisearch.Client) error {
documents := []map[string]interface{}{
{
"id": r.Id,
"author": r.GetString("author"),
"name": r.GetString("name"),
"description": r.GetString("description"),
"location": r.GetString("location"),
"distance": r.GetFloat("distance"),
"elevation_gain": r.GetFloat("elevation_gain"),
"duration": r.GetFloat("duration"),
"difficulty": r.Get("difficulty"),
"category": r.Get("category"),
"completed": len(r.GetStringSlice("summit_logs")) > 0,
"date": r.GetDateTime("date").Time().Unix(),
"created": r.GetDateTime("created").Time().Unix(),
"public": r.GetBool("public"),
"_geo": map[string]float64{
"lat": r.GetFloat("lat"),
"lng": r.GetFloat("lon"),
},
},
}
if _, err := client.Index("trails").AddDocuments(documents); err != nil {
return err
}
return nil
}
func generateMeilisearchToken(rules map[string]interface{}, client *meilisearch.Client) (resp string, err error) {
apiKeyUid := ""
apiKey := ""
if keys, err := client.GetKeys(nil); err != nil {
log.Fatal(err)
} else {
for _, k := range keys.Results {
if k.Name == "Default Search API Key" {
apiKeyUid = k.UID
apiKey = k.Key
}
}
}
if len(apiKey) == 0 || len(apiKeyUid) == 0 {
return "", errors.New("unable to locate meilisearch API key")
}
options := &meilisearch.TenantTokenOptions{
APIKey: apiKey,
}
return client.GenerateTenantToken(apiKeyUid, rules, options)
}

View File

@@ -0,0 +1,125 @@
package migrations
import (
"encoding/json"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/models/schema"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("xku110v5a5xbufa")
if err != nil {
return err
}
options := map[string]any{}
if err := json.Unmarshal([]byte(`{
"query": "SELECT id, username, avatar FROM users"
}`), &options); err != nil {
return err
}
collection.SetOptions(options)
// remove
collection.Schema.RemoveField("qzkmy7nv")
// add
new_username := &schema.SchemaField{}
if err := json.Unmarshal([]byte(`{
"system": false,
"id": "mbokwbb3",
"name": "username",
"type": "text",
"required": false,
"presentable": false,
"unique": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
}`), new_username); err != nil {
return err
}
collection.Schema.AddField(new_username)
// add
new_avatar := &schema.SchemaField{}
if err := json.Unmarshal([]byte(`{
"system": false,
"id": "60wozbto",
"name": "avatar",
"type": "file",
"required": false,
"presentable": false,
"unique": false,
"options": {
"mimeTypes": [
"image/jpeg",
"image/png",
"image/svg+xml",
"image/gif",
"image/webp"
],
"thumbs": null,
"maxSelect": 1,
"maxSize": 5242880,
"protected": false
}
}`), new_avatar); err != nil {
return err
}
collection.Schema.AddField(new_avatar)
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("xku110v5a5xbufa")
if err != nil {
return err
}
options := map[string]any{}
if err := json.Unmarshal([]byte(`{
"query": "SELECT id, username FROM users"
}`), &options); err != nil {
return err
}
collection.SetOptions(options)
// add
del_username := &schema.SchemaField{}
if err := json.Unmarshal([]byte(`{
"system": false,
"id": "qzkmy7nv",
"name": "username",
"type": "text",
"required": false,
"presentable": false,
"unique": false,
"options": {
"min": null,
"max": null,
"pattern": ""
}
}`), del_username); err != nil {
return err
}
collection.Schema.AddField(del_username)
// remove
collection.Schema.RemoveField("mbokwbb3")
// remove
collection.Schema.RemoveField("60wozbto")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,38 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
if err != nil {
return err
}
collection.ListRule = types.Pointer("id = @request.auth.id")
collection.ViewRule = types.Pointer("id = @request.auth.id")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("_pb_users_auth_")
if err != nil {
return err
}
collection.ListRule = types.Pointer("@request.auth.id != \"\"")
collection.ViewRule = types.Pointer("@request.auth.id != \"\"")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,38 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ListRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.trail = id && trail_share_via_trail.user = @request.auth.id)")
collection.ViewRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.trail = id && trail_share_via_trail.user = @request.auth.id)")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ListRule = types.Pointer("author = @request.auth.id || public = true")
collection.ViewRule = types.Pointer("author = @request.auth.id || public = true")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ListRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.user = @request.auth.id)")
collection.ViewRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.user = @request.auth.id)")
collection.UpdateRule = types.Pointer("author = @request.auth.id || (trail_share_via_trail.trail = id && trail_share_via_trail.user = @request.auth.id && trail_share_via_trail.permission = \"edit\")")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ListRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.trail = id && trail_share_via_trail.user = @request.auth.id)")
collection.ViewRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.trail = id && trail_share_via_trail.user = @request.auth.id)")
collection.UpdateRule = types.Pointer("author = @request.auth.id ")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,38 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("1mns8mlal6uf9ku")
if err != nil {
return err
}
collection.ListRule = types.Pointer("trail.author = @request.auth.id || user = @request.auth.id")
collection.ViewRule = types.Pointer("trail.author = @request.auth.id || user = @request.auth.id")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("1mns8mlal6uf9ku")
if err != nil {
return err
}
collection.ListRule = types.Pointer("trail.author = @request.auth.id")
collection.ViewRule = types.Pointer("trail.author = @request.auth.id")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,34 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ViewRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.user ?= @request.auth.id)")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ViewRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.user = @request.auth.id)")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,34 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ListRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.user ?= @request.auth.id)")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.ListRule = types.Pointer("author = @request.auth.id || public = true || (trail_share_via_trail.user = @request.auth.id)")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,34 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.UpdateRule = types.Pointer("author = @request.auth.id || (trail_share_via_trail.trail = id && trail_share_via_trail.user ?= @request.auth.id && trail_share_via_trail.permission = \"edit\")")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("e864strfxo14pm4")
if err != nil {
return err
}
collection.UpdateRule = types.Pointer("author = @request.auth.id || (trail_share_via_trail.trail = id && trail_share_via_trail.user = @request.auth.id && trail_share_via_trail.permission = \"edit\")")
return dao.SaveCollection(collection)
})
}

View File

@@ -0,0 +1,63 @@
package migrations
import (
"os"
"github.com/meilisearch/meilisearch-go"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"pocketbase/util"
)
func init() {
client := meilisearch.NewClient(meilisearch.ClientConfig{
Host: os.Getenv("MEILI_URL"),
APIKey: os.Getenv("MEILI_MASTER_KEY"),
})
m.Register(func(db dbx.Builder) error {
dao := daos.New(db)
var usernames []string
err := db.NewQuery("SELECT username FROM users").Column(&usernames)
if err != nil {
return err
}
for _, username := range usernames {
record, err := dao.FindAuthRecordByUsername("users", username)
if err != nil {
return err
}
searchRules := map[string]interface{}{
"cities500": map[string]string{},
"trails": map[string]string{
"filter": "public = true OR author = " + record.Id + " OR shares = " + record.Id,
},
}
if token, err := util.GenerateMeilisearchToken(searchRules, client); err != nil {
return err
} else {
record.Set("token", token)
if err := dao.SaveRecord(record); err != nil {
return err
}
}
}
return nil
}, func(db dbx.Builder) error {
// add down queries...
return nil
})
}

View File

@@ -0,0 +1,42 @@
package migrations
import (
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/daos"
m "github.com/pocketbase/pocketbase/migrations"
"github.com/pocketbase/pocketbase/tools/types"
)
func init() {
m.Register(func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
collection.ListRule = types.Pointer("((@request.auth.id != \"\" && trail.author = @request.auth.id) || trail.public = true) || author = @request.auth.id || trail.trail_share_via_trail.user ?= @request.auth.id")
collection.ViewRule = types.Pointer("((@request.auth.id != \"\" && trail.author = @request.auth.id) || trail.public = true) || author = @request.auth.id || trail.trail_share_via_trail.user ?= @request.auth.id")
collection.CreateRule = types.Pointer("@request.auth.id != \"\" && (trail.author = @request.auth.id || trail.public = true || trail.trail_share_via_trail.user ?= @request.auth.id)")
return dao.SaveCollection(collection)
}, func(db dbx.Builder) error {
dao := daos.New(db);
collection, err := dao.FindCollectionByNameOrId("lf06qip3f4d11yk")
if err != nil {
return err
}
collection.ListRule = types.Pointer("((@request.auth.id != \"\" && trail.author = @request.auth.id) || trail.public = true) || author = @request.auth.id")
collection.ViewRule = types.Pointer("((@request.auth.id != \"\" && trail.author = @request.auth.id) || trail.public = true) || author = @request.auth.id")
collection.CreateRule = types.Pointer("@request.auth.id != \"\" && (trail.author = @request.auth.id || trail.public = true)")
return dao.SaveCollection(collection)
})
}

97
db/util/meilisearch.go Normal file
View File

@@ -0,0 +1,97 @@
package util
import (
"errors"
"log"
"github.com/meilisearch/meilisearch-go"
"github.com/pocketbase/pocketbase/models"
)
func documentFromTrailRecord(r *models.Record, includeShares bool) map[string]interface{} {
document := map[string]interface{}{
"id": r.Id,
"author": r.GetString("author"),
"name": r.GetString("name"),
"description": r.GetString("description"),
"location": r.GetString("location"),
"distance": r.GetFloat("distance"),
"elevation_gain": r.GetFloat("elevation_gain"),
"duration": r.GetFloat("duration"),
"difficulty": r.Get("difficulty"),
"category": r.Get("category"),
"completed": len(r.GetStringSlice("summit_logs")) > 0,
"date": r.GetDateTime("date").Time().Unix(),
"created": r.GetDateTime("created").Time().Unix(),
"public": r.GetBool("public"),
"_geo": map[string]float64{
"lat": r.GetFloat("lat"),
"lng": r.GetFloat("lon"),
},
}
if includeShares {
document["shares"] = []string{}
}
return document
}
func IndexTrail(r *models.Record, client *meilisearch.Client) error {
documents := []map[string]interface{}{documentFromTrailRecord(r, true)}
if _, err := client.Index("trails").AddDocuments(documents); err != nil {
return err
}
return nil
}
func UpdateTrail(r *models.Record, client *meilisearch.Client) error {
documents := documentFromTrailRecord(r, false)
if _, err := client.Index("trails").UpdateDocuments(documents); err != nil {
return err
}
return nil
}
func UpdateTrailShares(trailId string, shares []string, client *meilisearch.Client) error {
documents := []map[string]interface{}{
{
"id": trailId,
"shares": shares,
},
}
if _, err := client.Index("trails").UpdateDocuments(documents); err != nil {
return err
}
return nil
}
func GenerateMeilisearchToken(rules map[string]interface{}, client *meilisearch.Client) (resp string, err error) {
apiKeyUid := ""
apiKey := ""
if keys, err := client.GetKeys(nil); err != nil {
log.Fatal(err)
} else {
for _, k := range keys.Results {
if k.Name == "Default Search API Key" {
apiKeyUid = k.UID
apiKey = k.Key
}
}
}
if len(apiKey) == 0 || len(apiKeyUid) == 0 {
return "", errors.New("unable to locate meilisearch API key")
}
options := &meilisearch.TenantTokenOptions{
APIKey: apiKey,
}
return client.GenerateTenantToken(apiKeyUid, rules, options)
}

View File

@@ -40,6 +40,7 @@
.tooltip {
position: relative;
z-index: 10;
}
.tooltip:before,
@@ -74,6 +75,7 @@
display: inline-block;
width: 32px;
height: 32px;
margin-top: 6px;
}
.spinner:after {

View File

@@ -8,6 +8,7 @@
<script lang="ts">
import { createEventDispatcher } from "svelte";
import { fly } from "svelte/transition";
export let items: DropdownItem[] = [];
export let size: string = "regular";
@@ -30,26 +31,38 @@
dispatch("change", item);
closeMenu();
}
function handleWindowClick(e: MouseEvent) {
if ((e.target as HTMLElement).parentElement?.classList.contains("dropdown-toggle")) {
return;
}
isOpen = false;
}
</script>
<svelte:window on:mouseup={() => (isOpen = false)} />
<svelte:window on:mouseup={handleWindowClick} />
<div class="dropdown relative">
<slot {toggleMenu}>
<button
class="btn-icon flex items-center justify-center"
on:click={toggleMenu}
type="button"
>
<i class="fa fa-ellipsis-vertical text-{size}"></i>
</button>
</slot>
<div class="dropdown-toggle">
<slot {toggleMenu}>
<button
class="btn-icon flex items-center justify-center"
on:click={toggleMenu}
type="button"
>
<i class="fa fa-ellipsis-vertical text-{size}"></i>
</button>
</slot>
</div>
{#if isOpen}
<ul
class="menu absolute bg-menu-background border border-input-border rounded-l-xl rounded-b-xl shadow-md right-0 overflow-hidden mt-2"
class:none={isOpen}
style="z-index: 1001"
in:fly={{ y: -10, duration: 150 }}
out:fly={{ y: -10, duration: 150 }}
>
{#each items as item}
<li

View File

@@ -28,7 +28,7 @@
class="relative w-full {size} max-h-full rounded-xl text-content"
>
<!-- Modal content -->
<div class="relative bg-background shadow">
<div class="relative bg-background shadow rounded-xl">
<!-- Modal header -->
<div
class="flex items-center justify-between p-4 md:p-5 border-b border-separator rounded-t"

View File

@@ -97,7 +97,9 @@
on:mousedown|stopPropagation={() => handleItemClick(item)}
on:keydown|stopPropagation={() => handleItemClick(item)}
>
<i class="fa fa-{item.icon} mr-6"></i>
<slot name="item-header" {item}>
<i class="fa fa-{item.icon} mr-6"></i>
</slot>
<div>
<p>{item.text}</p>

View File

@@ -8,6 +8,7 @@
formatTimeHHMM,
} from "$lib/util/format_util";
import { _ } from "svelte-i18n";
import TrailShareInfo from "./trail_share_info.svelte";
export let trail: Trail;
@@ -22,20 +23,25 @@
on:mouseleave
role="listitem"
>
{#if trail.public}
<div
class=" top-4 right-4 z-10 tooltip"
style="position: absolute!important"
data-title={$_("public")}
>
<i class="fa fa-globe"></i>
</div>
{/if}
<div
class="relative w-full min-h-40 max-h-48 overflow-hidden rounded-t-2xl"
>
<img src={thumbnail} alt="" />
</div>
{#if trail.public || trail.expand?.trail_share_via_trail?.length}
<div
class="flex absolute top-4 right-4 w-8 h-8 rounded-full items-center justify-center bg-background text-content"
>
{#if trail.public}
<span class="tooltip" data-title={$_("public")}>
<i class="fa fa-globe"></i>
</span>
{/if}
{#if trail.expand?.trail_share_via_trail?.length}
<TrailShareInfo {trail}></TrailShareInfo>
{/if}
</div>
{/if}
<div class="p-4">
<div>
<h4 class="font-semibold text-lg">{trail.name}</h4>
@@ -45,7 +51,7 @@
month: "long",
day: "2-digit",
year: "numeric",
timeZone: 'UTC'
timeZone: "UTC",
})}
</p>
{/if}
@@ -65,12 +71,12 @@
<div class="flex mt-1 gap-4 text-sm text-gray-500 whitespace-nowrap">
<span
><i class="fa fa-left-right mr-2"></i>{formatDistance(
trail.distance
trail.distance,
)}</span
>
<span
><i class="fa fa-up-down mr-2"></i>{formatElevation(
trail.elevation_gain
trail.elevation_gain,
)}</span
>
<span

View File

@@ -19,6 +19,8 @@
import JSZip from "jszip";
import { getFileURL, saveAs } from "$lib/util/file_util";
import TrailShareModal from "./trail_share_modal.svelte";
import { currentUser } from "$lib/stores/user_store";
import { pb } from "$lib/pocketbase";
export let trail: Trail;
export let mode: "overview" | "map";
@@ -28,6 +30,10 @@
let openExportModal: () => void;
let openShareModal: () => void;
const allowEdit =
trail.author == $currentUser?.id ||
trail.expand.trail_share_via_trail?.some((s) => s.permission == "edit");
const dropdownItems: DropdownItem[] = [
mode == "overview"
? { text: $_("show-on-map"), value: "show", icon: "map" }
@@ -49,9 +55,15 @@
: []),
{ text: $_("print"), value: "print", icon: "print" },
{ text: $_("add-to-list"), value: "list", icon: "bookmark" },
{ text: $_("share"), value: "share", icon: "share" },
{ text: $_("edit"), value: "edit", icon: "pen" },
{ text: $_("delete"), value: "delete", icon: "trash" },
...(trail.author != pb.authStore.model?.id
? []
: [{ text: $_("share"), value: "share", icon: "share" }]),
...(allowEdit
? [{ text: $_("edit"), value: "edit", icon: "pen" }]
: []),
...(trail.author == $currentUser?.id
? [{ text: $_("delete"), value: "delete", icon: "trash" }]
: []),
];
async function handleDropdownClick(item: { text: string; value: any }) {
@@ -189,4 +201,4 @@
bind:openModal={openExportModal}
on:export={(e) => exportTrail(e.detail)}
></TrailExportModal>
<TrailShareModal bind:openModal={openShareModal}></TrailShareModal>
<TrailShareModal {trail} bind:openShareModal></TrailShareModal>

View File

@@ -31,6 +31,7 @@
import Textarea from "../base/textarea.svelte";
import CommentCard from "../comment/comment_card.svelte";
import PhotoGallery from "../photo_gallery.svelte";
import TrailShareInfo from "./trail_share_info.svelte";
export let trail: Trail;
export let mode: "overview" | "map" = "map";
@@ -152,14 +153,31 @@
</script>
<div
class="trail-info-panel max-w-5xl mx-auto border border-input-border rounded-3xl overflow-x-hidden h-full"
class="trail-info-panel max-w-5xl mx-auto border border-input-border rounded-3xl h-full"
>
<div class="trail-info-panel-header sticky -top-44 z-10">
<section class="relative h-80">
<img class="w-full h-80" src={thumbnail} alt="" />
<img class="w-full h-80 rounded-3xl" src={thumbnail} alt="" />
<div
class="absolute bottom-0 w-full h-1/2 bg-gradient-to-b from-transparent to-black opacity-50"
></div>
{#if trail.public || trail.expand?.trail_share_via_trail?.length}
<div
class="flex absolute top-8 right-10 w-8 h-8 rounded-full items-center justify-center bg-white text-primary"
>
{#if trail.public}
<span
class="tooltip text-2xl"
data-title={$_("public")}
>
<i class="fa fa-globe"></i>
</span>
{/if}
{#if trail.expand?.trail_share_via_trail?.length}
<TrailShareInfo {trail} large={true}></TrailShareInfo>
{/if}
</div>
{/if}
<div
class="flex absolute justify-between items-end w-full bottom-8 left-0 px-8 gap-y-4"
>
@@ -193,7 +211,7 @@
</h3>
</div>
</div>
{#if $currentUser && $currentUser.id == trail.author}
{#if ($currentUser && $currentUser.id == trail.author) || trail.expand.trail_share_via_trail?.length}
<TrailDropdown {trail} {mode}></TrailDropdown>
{/if}
</div>

View File

@@ -1,5 +1,4 @@
<script lang="ts">
import { page } from "$app/stores";
import type { Trail } from "$lib/models/trail";
import { getFileURL } from "$lib/util/file_util";
import {
@@ -8,6 +7,7 @@
formatTimeHHMM,
} from "$lib/util/format_util";
import { _ } from "svelte-i18n";
import TrailShareInfo from "./trail_share_info.svelte";
export let trail: Trail;
@@ -23,20 +23,26 @@
<img class="h-28 w-28 object-cover rounded-xl" src={thumbnail} alt="" />
</div>
<div class="min-w-0 basis-full">
<h4 class="font-semibold text-lg">
{trail.name}{#if trail.public}
<div class="flex items-center gap-4">
<h4 class="font-semibold text-lg">
{trail.name}
</h4>
{#if trail.public}
<span class="tooltip ml-3" data-title={$_("public")}>
<i class="fa fa-globe"></i>
</span>
{/if}
</h4>
{#if trail.expand?.trail_share_via_trail?.length}
<TrailShareInfo {trail}></TrailShareInfo>
{/if}
</div>
{#if trail.date}
<p class="text-xs text-gray-500 mb-3">
{new Date(trail.date).toLocaleDateString(undefined, {
month: "long",
day: "2-digit",
year: "numeric",
timeZone: 'UTC'
timeZone: "UTC",
})}
</p>
{/if}
@@ -54,12 +60,12 @@
<div class="flex mt-1 gap-4 text-sm text-gray-500">
<span
><i class="fa fa-left-right mr-2"></i>{formatDistance(
trail.distance
trail.distance,
)}</span
>
<span
><i class="fa fa-up-down mr-2"></i>{formatElevation(
trail.elevation_gain
trail.elevation_gain,
)}</span
>
<span

View File

@@ -0,0 +1,125 @@
<script lang="ts">
import type { Trail } from "$lib/models/trail";
import type { User } from "$lib/models/user";
import { pb } from "$lib/pocketbase";
import { users_show } from "$lib/stores/user_store";
import { getFileURL } from "$lib/util/file_util";
import { _ } from "svelte-i18n";
import { fly, slide } from "svelte/transition";
export let trail: Trail;
export let large: boolean = false;
let showInfo: boolean = false;
let loading: boolean = false;
let infoLoaded: boolean = false;
let trailIsOwned: boolean = trail.author == pb.authStore.model?.id;
let author: User;
async function fetchInfo() {
if (!infoLoaded) {
loading = true;
loading = false;
if (trailIsOwned) {
for (const share of trail.expand.trail_share_via_trail ?? []) {
share.expand = {
user: await users_show(share.user),
};
}
} else {
author = await users_show(trail.author!);
}
infoLoaded = true;
}
showInfo = true;
}
</script>
<div class="relative trail-share-info">
<i
class="fa fa-share-nodes"
class:text-xl={large}
role="button"
tabindex="0"
on:mouseenter={fetchInfo}
on:mouseleave={() => (showInfo = false)}
></i>
{#if showInfo}
<ul
class="menu absolute top-7 bg-menu-background border border-input-border rounded-xl shadow-md overflow-hidden p-3 space-y-3 text-content"
in:fly={{y: -10, duration: 150}} out:fly={{y: -10, duration: 150}}
>
{#if loading}
<div class="spinner spinner-dark"></div>
{:else if infoLoaded && trail.expand.trail_share_via_trail}
{#if trailIsOwned}
{#each trail.expand.trail_share_via_trail as share}
{#if share.expand}
<li>
<div class="flex items-center mr-8">
<img
class="rounded-full w-8 aspect-square mr-2"
src={getFileURL(
share.expand.user,
share.expand.user.avatar,
) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${share.expand.user.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
<p class="font-semibold text-base">
{share.expand.user.username}
</p>
<span class="mx-2 text-sm text-gray-500"
>{$_("can")}</span
>
<p class="whitespace-nowrap text-base">
{#if share.permission == "view"}
<i class="fa fa-eye"></i>
{:else}
<i class="fa fa-pen"></i>
{/if}
</p>
</div>
</li>
{/if}
{/each}
{:else if author}
<li>
<p class="text-xs text-gray-500 mb-2">
{$_("shared-by")}
</p>
<div class="flex items-center mr-8">
<img
class="rounded-full w-8 aspect-square mr-2"
src={getFileURL(author, author.avatar) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${author.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
<p class="font-semibold">
{author.username}
</p>
</div>
<p class="text-xs text-gray-500 mt-2">
{$_("you-can")}
</p>
<p class="whitespace-nowrap">
{#if trail.expand.trail_share_via_trail[0].permission == "view"}
<i class="fa fa-eye mr-1"></i>
{$_("view")}
{:else}
<i class="fa fa-pen mr-1"></i>
{$_("edit")}
{/if}
</p>
</li>
{/if}
{/if}
</ul>
{/if}
</div>

View File

@@ -1,15 +1,35 @@
<script lang="ts">
import Modal from "$lib/components/base/modal.svelte";
import type { Trail } from "$lib/models/trail";
import { TrailShare } from "$lib/models/trail_share";
import type { User } from "$lib/models/user";
import { show_toast } from "$lib/stores/toast_store";
import {
shares,
trail_share_create,
trail_share_delete,
trail_share_index,
trail_share_update,
} from "$lib/stores/trail_share_store";
import { users_search } from "$lib/stores/user_store";
import { getFileURL } from "$lib/util/file_util";
import { createEventDispatcher } from "svelte";
import { _ } from "svelte-i18n";
import Button from "../base/button.svelte";
import Search, { type SearchItem } from "../base/search.svelte";
import { users_search } from "$lib/stores/user_store";
import type { User } from "$lib/models/user";
import { show_toast } from "$lib/stores/toast_store";
import type { SelectItem } from "../base/select.svelte";
import Select from "../base/select.svelte";
export let openModal: (() => void) | undefined = undefined;
let openModal: (() => void) | undefined = undefined;
export let closeModal: (() => void) | undefined = undefined;
export function openShareModal() {
fetchShares();
if (openModal) {
openModal();
}
}
export let trail: Trail;
const dispatch = createEventDispatcher();
@@ -17,14 +37,21 @@
let searchItems: SearchItem[] = [];
let sharesLoading: boolean = false;
const permissionSelectItems: SelectItem[] = [
{ text: $_("view"), value: "view" },
{ text: $_("edit"), value: "edit" },
];
async function updateUsers(q: string) {
try {
const users: User[] = await users_search(q);
searchItems = users.map((u) => ({
text: u.username!,
value: u.id,
icon: "user"
}))
value: u,
icon: "user",
}));
} catch (e) {
console.error(e);
show_toast({
@@ -47,21 +74,90 @@
dispatch("save");
closeModal!();
}
async function shareTrail(item: SelectItem) {
const share = new TrailShare(item.value.id, trail.id!, "view");
await trail_share_create(share);
fetchShares();
}
async function updateSharePermission(share:TrailShare, permission: "view"| "edit" ) {
share.permission = permission;
await trail_share_update(share);
}
async function deleteShare(share: TrailShare) {
await trail_share_delete(share);
fetchShares();
}
async function fetchShares() {
sharesLoading = true;
await trail_share_index(trail.id!);
sharesLoading = false;
}
</script>
<Modal
id="share-modal"
title="Share this trail"
size="max-w-lg"
title={$_('share-this-trail')}
size="max-w-sm overflow-visible"
bind:openModal
bind:closeModal
>
<div slot="content">
<Search
on:update={(e) => updateUsers(e.detail)}
on:click={(e) => shareTrail(e.detail)}
placeholder={`${$_("username")}`}
items={searchItems}
></Search>
>
<img
slot="item-header"
let:item
class="rounded-full w-8 aspect-square mr-2"
src={getFileURL(item.value, item.value.avatar) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${item.value.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
</Search>
<h4 class="font-semibold mt-4">{$_('shared-with')}</h4>
{#if $shares.length == 0}
<p class="text-gray-500 text-center mt-2 text-sm">
{$_('trail-not-shared')}
</p>
{:else}
{#each $shares as share}
{#if share.expand}
<div class="flex items-center gap-x-2 p-2">
<img
class="rounded-full w-8 aspect-square mr-2"
src={getFileURL(
share.expand.user,
share.expand.user.avatar,
) ||
`https://api.dicebear.com/7.x/initials/svg?seed=${share.expand.user.username}&backgroundType=gradientLinear`}
alt="avatar"
/>
<p>{share.expand.user.username}</p>
<span class="basis-full text-sm text-center text-gray-500">{$_('can')}</span>
<div class="shrink-0">
<Select
bind:value={share.permission}
items={permissionSelectItems}
on:change={(e) => updateSharePermission(share, e.detail)}
></Select>
</div>
<button class="btn-icon text-red-500"
on:click={() => deleteShare(share)}
><i class="fa fa-trash"></i></button
>
</div>
{/if}
{/each}
{/if}
</div>
<div slot="footer" class="flex justify-between items-center gap-4">
<Button

View File

@@ -11,6 +11,7 @@
"api-documentation": "API Dokumentation",
"avatar": "Avatar",
"basic-info": "Basisinformation",
"can": "kann",
"cancel": "Abbrechen",
"card": "{n, plural, =1 {Karte} other {Karten}}",
"categories": "Kategorien",
@@ -23,7 +24,7 @@
"completed": "Abgeschlossen",
"completion-status": "Abschlussstatus",
"contribute": "Mitwirken",
"copy-link": "",
"copy-link": "Link kopieren",
"create-new-list": "Neue Liste erstellen",
"creation-date": "Erstellungsdatum",
"cycling": "Radfahren",
@@ -133,7 +134,10 @@
"search-trails": "Route suchen",
"select-list": "Liste auswählen",
"settings": "Einstellungen",
"share": "",
"share": "Teilen",
"share-this-trail": "Diese Route teilen",
"shared-by": "Geteilt von",
"shared-with": "Geteilt mit",
"show-in-overview": "In der Übersicht anzeigen",
"show-on-map": "Auf der Karte anzeigen",
"slogan": "Speichere deine Abenteuer!",
@@ -142,12 +146,15 @@
"summit-book": "Gipfelbuch",
"text": "Text",
"trail": "{n, plural, =1 {Route} other {Routen}}",
"trail-not-shared": "Route mit niemandem geteilt",
"trails-for-you": "Routen für dich",
"units": "Einheiten",
"upload-file": "Datei hochladen",
"upload-gpx": "GPX hochladen",
"username": "Nutzername",
"view": "Ansehen",
"waypoints": "{n, plural, =1 {Wegpunkt} other {Wegpunkte}}",
"welcome_to": "Willkommen bei",
"wrong-username-or-password": "Falscher Nutzername oder falsches Passwort"
"wrong-username-or-password": "Falscher Nutzername oder falsches Passwort",
"you-can": "Sie können"
}

View File

@@ -11,6 +11,7 @@
"api-documentation": "API Documentation",
"avatar": "Avatar",
"basic-info": "Basic Info",
"can": "can",
"cancel": "Cancel",
"card": "{n, plural, =1 {Card} other {Cards}}",
"categories": "Categories",
@@ -134,6 +135,9 @@
"select-list": "Select List",
"settings": "Settings",
"share": "Share",
"share-this-trail": "Share this trail",
"shared-by": "Shared by",
"shared-with": "Shared with",
"show-in-overview": "Show in overview",
"show-on-map": "Show on map",
"slogan": "Save your adventures!",
@@ -142,12 +146,15 @@
"summit-book": "Summit Book",
"text": "Text",
"trail": "{n, plural, =1 {Trail} other {Trails}}",
"trail-not-shared": "Not shared with anyone",
"trails-for-you": "Trails for you",
"units": "Units",
"upload-file": "Upload file",
"upload-gpx": "Upload GPX",
"username": "Username",
"view": "View",
"waypoints": "{n, plural, =1 {Waypoint} other {Waypoints}}",
"welcome_to": "Welcome to",
"wrong-username-or-password": "Wrong username or password"
"wrong-username-or-password": "Wrong username or password",
"you-can": "You can"
}

View File

@@ -11,6 +11,7 @@
"api-documentation": "Documentation API",
"avatar": "Avatar",
"basic-info": "Informations de base",
"can": "",
"cancel": "Annuler",
"card": "{n, plural, =1 {Carte} other {Cartes}}",
"categories": "Catégories",
@@ -134,6 +135,9 @@
"select-list": "Liste de choix",
"settings": "Paramètres",
"share": "",
"share-this-trail": "",
"shared-by": "",
"shared-with": "",
"show-in-overview": "Voir dans l'aperçu",
"show-on-map": "Voir sur la carte",
"slogan": "Sauvegarder vos aventures !",
@@ -142,12 +146,15 @@
"summit-book": "Livre du sommet",
"text": "Texte",
"trail": "{n, plural, =1 {Itinéraire} other {Itinéraires}}",
"trail-not-shared": "",
"trails-for-you": "Itinéraire pour vous",
"units": "Unités",
"upload-file": "Téléverser un fichier",
"upload-gpx": "Envoyer un GPX",
"username": "Nom d'utilisteur",
"view": "",
"waypoints": "Point de repère",
"welcome_to": "Bienvenue à",
"wrong-username-or-password": "Nom d'utilisateur ou mot de passe incorrect"
"wrong-username-or-password": "Nom d'utilisateur ou mot de passe incorrect",
"you-can": ""
}

View File

@@ -11,6 +11,7 @@
"api-documentation": "API Dokumentáció",
"avatar": "Avatar",
"basic-info": "Alap információk",
"can": "",
"cancel": "Mégsem",
"card": "{n, plural, =1 {Kártya} other {Kártyák}}",
"categories": "Kategóriák",
@@ -134,6 +135,9 @@
"select-list": "Lista kiválasztása",
"settings": "Beállítások",
"share": "",
"share-this-trail": "",
"shared-by": "",
"shared-with": "",
"show-in-overview": "Áttekintés",
"show-on-map": "Mutatás térképen",
"slogan": "Mentse el a kalandjait!",
@@ -142,12 +146,15 @@
"summit-book": "Csúcspont könyv",
"text": "Szöveg",
"trail": "{n, plural, =1 {Útvonal} other {Útvonalak}}",
"trail-not-shared": "",
"trails-for-you": "Útvonalak önnek",
"units": "Mértékegységek",
"upload-file": "Fájl feltöltése",
"upload-gpx": "GPX feltöltése",
"username": "Felhasználónév",
"view": "",
"waypoints": "Útvonalpontok",
"welcome_to": "Üdvözöljük a",
"wrong-username-or-password": "Helytelen felhasználónév vagy jelszó"
"wrong-username-or-password": "Helytelen felhasználónév vagy jelszó",
"you-can": ""
}

View File

@@ -11,6 +11,7 @@
"api-documentation": "API-documentatie",
"avatar": "Profielfoto",
"basic-info": "Algemene informatie",
"can": "",
"cancel": "Annuleren",
"card": "{n, plural, =1 {kaart} other {kaarten}}",
"categories": "Categorieën",
@@ -134,6 +135,9 @@
"select-list": "Kies een lijst",
"settings": "Instellingen",
"share": "",
"share-this-trail": "",
"shared-by": "",
"shared-with": "",
"show-in-overview": "Tonen op overzicht",
"show-on-map": "Tonen op kaart",
"slogan": "Bewaar je avonturen!",
@@ -142,12 +146,15 @@
"summit-book": "Bergtopboek",
"text": "Tekst",
"trail": "{n, plural, =1 {Wandelroute} other {Wandelroutes}}",
"trail-not-shared": "",
"trails-for-you": "Wandelroutes voor jou",
"units": "Eenheden",
"upload-file": "Bestand uploaden",
"upload-gpx": "GPX-bestand uploaden",
"username": "Gebruikersnaam",
"view": "",
"waypoints": "Routepunten",
"welcome_to": "Welkom bij",
"wrong-username-or-password": "Onjuiste gebruikersnaam of wachtwoord"
"wrong-username-or-password": "Onjuiste gebruikersnaam of wachtwoord",
"you-can": ""
}

View File

@@ -11,6 +11,7 @@
"api-documentation": "Dokumentacja API",
"avatar": "Awatar",
"basic-info": "Podstawowe informacje",
"can": "",
"cancel": "Anuluj",
"card": "{n, plural, =1 {Karta} other {Karty}}",
"categories": "Kategorie",
@@ -134,6 +135,9 @@
"select-list": "Wybierz Listę",
"settings": "Ustawienia",
"share": "",
"share-this-trail": "",
"shared-by": "",
"shared-with": "",
"show-in-overview": "Pokaż w przeglądzie",
"show-on-map": "Pokaż na mapie",
"slogan": "Zapisz swoją wyprawę!",
@@ -142,12 +146,15 @@
"summit-book": "Logbook",
"text": "Tekst",
"trail": "{n, plural, =1 {Szlak} other {Szlaki}}",
"trail-not-shared": "",
"trails-for-you": "Ścieżki dla ciebie",
"units": "Jednostki",
"upload-file": "Przesyłanie pliku",
"upload-gpx": "Importuj GPX",
"username": "Nazwa Użytkownika",
"view": "",
"waypoints": "Punkty",
"welcome_to": "Witaj w",
"wrong-username-or-password": "Zła nazwa użytkownika lub hasło"
"wrong-username-or-password": "Zła nazwa użytkownika lub hasło",
"you-can": ""
}

View File

@@ -11,6 +11,7 @@
"api-documentation": "Documentação da API",
"avatar": "Avatar",
"basic-info": "Informações básicas",
"can": "",
"cancel": "Cancelar",
"card": "{n, plural, =1 {Cartão} other {cartãos}}",
"categories": "Categorias",
@@ -134,6 +135,9 @@
"select-list": "Selecionar lista",
"settings": "Definições",
"share": "",
"share-this-trail": "",
"shared-by": "",
"shared-with": "",
"show-in-overview": "Mostrar na vista geral",
"show-on-map": "Mostrar no mapa",
"slogan": "Guarde as suas aventuras!",
@@ -142,12 +146,15 @@
"summit-book": "Livro da cimeira",
"text": "Texto",
"trail": "{n, plural, =1 {Percurso} other {Percursos}}",
"trail-not-shared": "",
"trails-for-you": "Trilhos para si",
"units": "Unidades",
"upload-file": "Subir arquivo",
"upload-gpx": "Carregar GPX",
"username": "Nome de utilizador",
"view": "",
"waypoints": "Pontos de passagem",
"welcome_to": "Bem-vindo ao",
"wrong-username-or-password": "Nome de utilizador ou palavra-passe errados"
"wrong-username-or-password": "Nome de utilizador ou palavra-passe errados",
"you-can": ""
}

View File

@@ -11,6 +11,7 @@
"api-documentation": "API 文档",
"avatar": "头像",
"basic-info": "基本信息",
"can": "",
"cancel": "取消",
"card": "{n, plural, =1 {卡片} other {卡片}}",
"categories": "分类",
@@ -134,6 +135,9 @@
"select-list": "选择列表",
"settings": "设置",
"share": "",
"share-this-trail": "",
"shared-by": "",
"shared-with": "",
"show-in-overview": "详情中展示",
"show-on-map": "地图中展示",
"slogan": "保存你的冒险!",
@@ -142,12 +146,15 @@
"summit-book": "详细日程",
"text": "文本",
"trail": "{n, plural, =1 {路线} other {路线}}",
"trail-not-shared": "",
"trails-for-you": "推荐路线",
"units": "单位",
"upload-file": "上传文件",
"upload-gpx": "上传 GPX",
"username": "用户名",
"view": "",
"waypoints": "坐标",
"welcome_to": "欢迎",
"wrong-username-or-password": "用户名或密码无效"
"wrong-username-or-password": "用户名或密码无效",
"you-can": ""
}

View File

@@ -1,6 +1,7 @@
import type { Category } from "./category";
import type { Comment } from "./comment";
import type { SummitLog } from "./summit_log";
import type { TrailShare } from "./trail_share";
import type { Waypoint } from "./waypoint";
class Trail {
@@ -28,6 +29,7 @@ class Trail {
summit_logs: SummitLog[]
comments_via_trail: Comment[]
gpx_data?: string
trail_share_via_trail?: TrailShare[]
}
tags?: string[];
description?: string;
@@ -52,6 +54,7 @@ class Trail {
waypoints?: Waypoint[],
summit_logs?: SummitLog[],
comments?: Comment[],
shares?: TrailShare[],
tags?: string[],
description?: string
created?: string
@@ -78,7 +81,8 @@ class Trail {
category: params?.category,
waypoints: params?.waypoints ?? [],
summit_logs: params?.summit_logs ?? [],
comments_via_trail: params?.comments ?? []
comments_via_trail: params?.comments ?? [],
trail_share_via_trail: params?.shares ?? []
}
this.tags = params?.tags ?? []
this.description = params?.description ?? "";

View File

@@ -0,0 +1,17 @@
import type { User } from "./user";
export class TrailShare {
id?: string;
user: string;
trail: string;
permission: "view" | "edit"
expand?: {
user: User
}
constructor(user: string, trail: string, permission: "view" | "edit") {
this.user = user;
this.trail = trail;
this.permission = permission
}
}

View File

@@ -0,0 +1,57 @@
import type { TrailShare } from "$lib/models/trail_share";
import { ClientResponseError } from "pocketbase";
import { writable, type Writable } from "svelte/store";
export const shares: Writable<TrailShare[]> = writable([])
export async function trail_share_index(trail: string, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const r = await f('/api/v1/trail-share?' + new URLSearchParams({
filter: `trail='${trail}'`,
}), {
method: 'GET',
})
if (!r.ok) {
throw new ClientResponseError(await r.json())
}
const response: TrailShare[] = await r.json();
shares.set(response);
return shares;
}
export async function trail_share_create(share: TrailShare) {
let r = await fetch('/api/v1/trail-share', {
method: 'PUT',
body: JSON.stringify(share),
})
if (!r.ok) {
throw new ClientResponseError(await r.json())
}
}
export async function trail_share_update(share: TrailShare) {
let r = await fetch('/api/v1/trail-share/' + share.id, {
method: 'POST',
body: JSON.stringify(share),
})
if (!r.ok) {
throw new ClientResponseError(await r.json())
}
}
export async function trail_share_delete(share: TrailShare) {
const r = await fetch('/api/v1/trail-share/' + share.id, {
method: 'DELETE',
})
if (!r.ok) {
throw new ClientResponseError(await r.json())
}
}

View File

@@ -55,7 +55,7 @@ export async function trails_search_filter(filter: TrailFilter, page: number = 1
}
r = await f('/api/v1/trail?' + new URLSearchParams({
expand: "category,waypoints,summit_logs",
expand: "category,waypoints,summit_logs,trail_share_via_trail",
filter: trailIds.map((id: Record<string, any>) => `id="${id}"`).join('||'),
sort: `${filter.sortOrder}${filter.sort}`
}), {
@@ -131,7 +131,7 @@ export async function trails_search_bounding_box(northEast: LatLng, southWest: L
export async function trails_show(id: string, loadGPX?: boolean, f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch) {
const r = await f(`/api/v1/trail/${id}?` + new URLSearchParams({
expand: "category,waypoints,summit_logs,comments_via_trail.author",
expand: "category,waypoints,summit_logs,comments_via_trail.author,trail_share_via_trail",
}), {
method: 'GET',
})

View File

@@ -24,8 +24,8 @@ export async function users_create(user: User) {
}
export async function users_search(q: string) {
let r = await fetch('/api/v1/user?' + new URLSearchParams({
"filter": `username~"${q}"`,
let r = await fetch('/api/v1/user/anonymous?' + new URLSearchParams({
"filter": `username~"${q}"&&id!="${pb.authStore.model?.id}"`,
}), {
method: 'GET',
})
@@ -38,6 +38,19 @@ export async function users_search(q: string) {
}
}
export async function users_show(id: string) {
let r = await fetch(`/api/v1/user/anonymous/${id}`, {
method: 'GET',
})
const response = await r.json()
if (r.ok) {
return response;
} else {
throw new ClientResponseError(response)
}
}
export async function users_auth_methods(f: (url: RequestInfo | URL, config?: RequestInit) => Promise<Response> = fetch): Promise<AuthMethodsList> {
const r = await f('/api/v1/auth/oauth', {
method: 'GET',

View File

@@ -0,0 +1,36 @@
import type { TrailShare } from '$lib/models/trail_share';
import type { User } from '$lib/models/user';
import { pb } from '$lib/pocketbase';
import { error, json, type RequestEvent } from '@sveltejs/kit';
export async function GET(event: RequestEvent) {
const sort = event.url.searchParams.get('sort') ?? ""
const filter = event.url.searchParams.get("filter") ?? "";
try {
const r: TrailShare[] = await pb.collection('trail_share').getFullList<TrailShare>({
sort: sort,
filter: filter
})
for (const share of r) {
const anonymous_user = await pb.collection('users_anonymous').getOne<User>(share.user)
share.expand = {
user: anonymous_user
}
}
return json(r)
} catch (e: any) {
throw error(e.status, e);
}
}
export async function PUT(event: RequestEvent) {
const data = await event.request.json();
try {
const r = await pb.collection('trail_share').create<TrailShare>(data)
return json(r);
} catch (e: any) {
throw error(e.status, e)
}
}

View File

@@ -0,0 +1,33 @@
import type { TrailShare } from "$lib/models/trail_share";
import { pb } from "$lib/pocketbase";
import { error, json, type RequestEvent } from "@sveltejs/kit";
export async function GET(event: RequestEvent) {
try {
const r = await pb.collection('trail_share')
.getOne<TrailShare>(event.params.id as string)
return json(r)
} catch (e: any) {
throw error(e.status, e);
}
}
export async function POST(event: RequestEvent) {
const data = await event.request.json()
try {
const r = await pb.collection('trail_share').update<TrailShare>(event.params.id as string, data)
return json(r);
} catch (e: any) {
throw error(e.status, e)
}
}
export async function DELETE(event: RequestEvent) {
try {
const r = await pb.collection('trail_share').delete(event.params.id as string)
return json({ 'acknowledged': r });
} catch (e: any) {
throw error(e.status, e)
}
}

View File

@@ -4,22 +4,6 @@ import { pb } from '$lib/pocketbase';
import { error, json, type RequestEvent } from '@sveltejs/kit'
import { ClientResponseError } from 'pocketbase';
export async function GET(event: RequestEvent) {
const page = event.url.searchParams.get("page") ?? "0";
const perPage = event.url.searchParams.get("per-page") ?? "10";
const sort = event.url.searchParams.get("sort") ?? ""
const filter = event.url.searchParams.get("filter") ?? "";
try {
const r = await pb.collection('users_anonymous')
.getList<User>(parseInt(page), parseInt(perPage), { sort: sort ?? "", filter: filter ?? "" })
return json(r)
} catch (e: any) {
throw error(e.status, e);
}
}
export async function PUT(event: RequestEvent) {
const data = await event.request.json()
try {

View File

@@ -1,5 +1,5 @@
import type { User } from '$lib/models/user';
import { pb } from '$lib/pocketbase';
import type { User } from '$lib/stores/user_store';
import { error, json, type RequestEvent } from '@sveltejs/kit'
export async function GET(event: RequestEvent) {

View File

@@ -0,0 +1,19 @@
import type { User } from '$lib/models/user';
import { pb } from '$lib/pocketbase';
import { error, json, type RequestEvent } from '@sveltejs/kit';
export async function GET(event: RequestEvent) {
const page = event.url.searchParams.get("page") ?? "0";
const perPage = event.url.searchParams.get("per-page") ?? "10";
const sort = event.url.searchParams.get("sort") ?? ""
const filter = event.url.searchParams.get("filter") ?? "";
try {
const r = await pb.collection('users_anonymous')
.getList<User>(parseInt(page), parseInt(perPage), { sort: sort ?? "", filter: filter ?? "" })
return json(r)
} catch (e: any) {
throw error(e.status, e);
}
}

View File

@@ -0,0 +1,13 @@
import type { User } from '$lib/models/user';
import { pb } from '$lib/pocketbase';
import { error, json, type RequestEvent } from '@sveltejs/kit'
export async function GET(event: RequestEvent) {
try {
const r = await pb.collection('users_anonymous')
.getOne<User>(event.params.id as string)
return json(r)
} catch (e: any) {
throw error(e.status, e);
}
}