From 749f999f2aade7c3b40ae7fe305d7ec9a2d271bf Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 30 Jul 2025 12:29:36 -0400 Subject: [PATCH] feat: better endpoint descriptions (#20439) --- mobile/openapi/lib/api/activities_api.dart | Bin 7646 -> 8102 bytes mobile/openapi/lib/api/albums_api.dart | Bin 19232 -> 20429 bytes mobile/openapi/lib/api/api_keys_api.dart | Bin 7918 -> 8459 bytes mobile/openapi/lib/api/assets_api.dart | Bin 33087 -> 34275 bytes .../openapi/lib/api/authentication_api.dart | Bin 15181 -> 15631 bytes mobile/openapi/lib/api/deprecated_api.dart | Bin 2209 -> 2315 bytes mobile/openapi/lib/api/download_api.dart | Bin 4453 -> 4674 bytes mobile/openapi/lib/api/duplicates_api.dart | Bin 4120 -> 4453 bytes mobile/openapi/lib/api/faces_api.dart | Bin 6262 -> 6704 bytes mobile/openapi/lib/api/jobs_api.dart | Bin 4667 -> 5155 bytes mobile/openapi/lib/api/libraries_api.dart | Bin 12490 -> 13643 bytes mobile/openapi/lib/api/map_api.dart | Bin 5455 -> 5455 bytes mobile/openapi/lib/api/memories_api.dart | Bin 14818 -> 15709 bytes mobile/openapi/lib/api/notifications_api.dart | Bin 9840 -> 10549 bytes mobile/openapi/lib/api/partners_api.dart | Bin 6582 -> 7031 bytes mobile/openapi/lib/api/people_api.dart | Bin 18930 -> 20147 bytes mobile/openapi/lib/api/search_api.dart | Bin 25498 -> 26516 bytes mobile/openapi/lib/api/server_api.dart | Bin 21309 -> 22275 bytes mobile/openapi/lib/api/sessions_api.dart | Bin 8383 -> 9031 bytes mobile/openapi/lib/api/shared_links_api.dart | Bin 15177 -> 15748 bytes mobile/openapi/lib/api/stacks_api.dart | Bin 10536 -> 11293 bytes mobile/openapi/lib/api/sync_api.dart | Bin 8774 -> 9258 bytes mobile/openapi/lib/api/system_config_api.dart | Bin 6365 -> 6999 bytes .../openapi/lib/api/system_metadata_api.dart | Bin 6193 -> 6790 bytes mobile/openapi/lib/api/tags_api.dart | Bin 14782 -> 15729 bytes mobile/openapi/lib/api/timeline_api.dart | Bin 11917 -> 12122 bytes mobile/openapi/lib/api/trash_api.dart | Bin 4776 -> 5071 bytes mobile/openapi/lib/api/users_admin_api.dart | Bin 16852 -> 18328 bytes mobile/openapi/lib/api/users_api.dart | Bin 21973 -> 23615 bytes open-api/immich-openapi-specs.json | 597 ++++++++++++------ open-api/typescript-sdk/src/fetch-client.ts | 522 ++++++++++++++- server/src/enum.ts | 5 + server/src/middleware/auth.guard.ts | 12 +- server/src/utils/misc.ts | 34 +- 34 files changed, 948 insertions(+), 222 deletions(-) diff --git a/mobile/openapi/lib/api/activities_api.dart b/mobile/openapi/lib/api/activities_api.dart index 5c83ba7db98cdeba9435a404ce07dab95b094dc8..67015499fa616cd7f4149ecc5a7168ca19a93f76 100644 GIT binary patch delta 848 zcmca-z07{YCdT@ZjLc$%)V!2}{LH)(g`(8L(#)dNVug~7RE31Zs?wON%_ikUc1rKIMh(#%sTn|E@Q z5$P$M4gq>fYw}JGiOE^q|B3SxFrHFq5lspKn|JcCu-Xt6NjMw<^v$`=Ekf^!jGp3> n#FEV7lFZ~{YI|t%W}djsYT~@iPDFVJuS0;IO4!^Z6~qhx5V#^n delta 438 zcmZ2xf6scuCPvSI)S|TfqTFJI#5@I$kdOcc^#K3i5C#3jH5`~DYe8~p)^^5k7IK!DmmjDB3D4Vws>M7)!0S4pKcty9?SDOuHmODfLjTCE~$~-DU@}(Cn@|vx1=X zFBCrzJ*g)l2aOK)ARhb!{s6Du3&ooU!O3nyy-astlgr-r<$d=3zW3X=FEc;hWV)Tq zPNU^eOkCUd9GBsMJPw_JP|R8cZ(7@1VY^N#VR|zl79*S3Cqdhx)bU&$VQd&i{KU6C zMk+WGYZKP;Y$3(Mz>Sqw8jUslV4YCkb18ZF->dKi-GuJ^MeuVq{$6WlYiSL^C$!R2 zSqcQNB1z*t_*eJ~bovztXD+Fe*8?zi<}rRPyjs8|Ty4?rN$XFE!X3Mc$qNs1RLLtx}*v;yS0<~2j2EHIRF3v delta 1113 zcmX>*pK-x7#to|&#R5``((;RPixm>{6g)yg0uP>zq>oNI)sp{keCf>;f+#H*iGxae~ej)3K zBKV!{F0(&&yYv%tl1g)n^{X>eYV}KtQ;Uk#iMM(4H14BJVB4l~>una`7hrb9VvB!p zhyv6a;>}jtyhCU%$ZYA!JA_Oo3-AkX{weyN$p_PX7grzG5LcKDV2==QjrHX9wt|~i zN&14UGMRi|lzno&AKTHo3dPJwl2#n;*)0vH*>rF*(Ccc(bUoHM28*vx`fB z@m^e#nT#(kHt$gLX4>qm$-(S`*EHh8LTmDSgPD`x2yrd$(FLU;<<0L6H1=Ev|#B#w@XS1(mGjkM9qcKvYel;jz#|fshii^u4I~g!#55Vt(!R= zr5L?2Ee&uCarPiH0eMW$_2Qmv@1{9-}SiV&5q diff --git a/mobile/openapi/lib/api/api_keys_api.dart b/mobile/openapi/lib/api/api_keys_api.dart index cf54ac5c04cccf2ca84ca510c4ca9741c7ce4941..e86c63bc6eee26443e45fdb76d4c2cc8f419b892 100644 GIT binary patch delta 1011 zcmaE7+wHVr4P$*sMrN@>YF($RPf6$Nwrb{8H{8F1mnU*ryP~wouiu_8Oud)O&6XTtf)SOfrddF(AHxt+9gB$@w zc?qXufL?N%?8E(=7#{)SCxtfAlUOuao8JQLqkBAFOjblh5)Q{~R^(S^P9|SJ(P?dS zosboi1u%6&QY8MQjp5kMTSYvHN=2mwDYVQK#*?Q@JA=dhqQoSkQW8!F0aKFo=IPSm F%mDdbQE31G delta 482 zcmeBndS|;~4WoNNYEfE#QEst9VxEFWNJxN!dVqg$h=P7%L8fkYYGtvyLViJNQDRAE zejZRsib7FpNoi4Du|i2kszP*7YH>k+UU6!y-ef^erO6(wW|Qyoa&2y9N@bcX!707j zgEffR57P!0S0C39SA-q<)tM=^L|U|2kaG^maO=t1Jiom$&31Q1ay%&p1AXAL`8lr_ z#PB*+w#k2G`8FREILl;3z!p3%-~3V7iizE=6c}cyHj@=4#W%NzX)t4Pc0efk&bHnh WCv_j>Y?H}xQqGfsPTvf4Ix_&HHl@q} diff --git a/mobile/openapi/lib/api/assets_api.dart b/mobile/openapi/lib/api/assets_api.dart index 3cb62785becbcff287a9fe4241808520a5f2ffb4..c0de1a0801f9cb296a5ecbff3dba02b2394056a7 100644 GIT binary patch delta 1508 zcmdnr#PqnEX@jbuX-Gz9u|jHIN2hrD zRTW@1BHbX6LpC4K$YHi5thcx%u_Uv&Br~}fJxr1(pHEc;Vvb3Mc9W}Bg(lxL6yL0? z+s|x4uBqS{gBrTY@Da1Ao&sT`u!U0cW>?cIOeW-L2fM-5RCIHgMFcYukyMtMT8KsO7NJfTL_vr&*dWq<*~x_N!&IdYTd<^{F$ FnE{QQIBfs` delta 575 zcmaFd&9uLXX@jcZ_7zF9g=9TZDI4Pl-@J0~)2&d%D#1u_cA+rbVBLMaU2mSmLXCgmk&BFCWB VYF^8%P&c_QUDv5n_7~Qp8_M7oG5q5WCu;9$@)xIlmF?8Z;oJPW5(;bg3LVU z{FGF^(t?!4l2mH@3luO4lih(1n!{~4xm%2DGcRW@lPx|^5_AyIf0~=;aC3+e<*$^~ zoKzb6YqPY{QsVrB(;*=LOqN#CpIm3cwpmU?$jsAC&QD2&>(NzXpWMJ>2-dfjGZ(CHGEi`H z0}qE7P_K}vi>r@oh%0XWW?;QZ$~h1_b=5)`CtJ(Pa$vPeTU#HjJX#|QVU@P_6F~rB CFiUa( diff --git a/mobile/openapi/lib/api/deprecated_api.dart b/mobile/openapi/lib/api/deprecated_api.dart index 7aa9662c2363a81be18e74aa1aeab244545efaae..f9a496b990dfea3e7be9192e8ee3ad91f41723f7 100644 GIT binary patch delta 125 zcmZ1|*e$f-7Ne=2LP$ntu|jHIN!2tjLc$%)V!2}{LH)(g`(8L(#)dNVug~7RE31Z;^Nd2y_Ed&yqx^R zlmvx>)S}$X;^NHwJUuQ21$}*e2&v$gUy^F205&N%wIm}y1!zu5X;B`;7>|&U0EOtF z)Z&8tyyDbYRIQVba!PNOXIjK;OOZn+@8eXOEYFm_*_lnBd7%BY`6%Z(%KbBOvn-zn FGXVR|k4pdm delta 204 zcmX@4@>FTVI!6D1)S|TfqTFJI#5@I$kdOcc^#K3i5C#2|{PMh<{KORf#G>Sk%(7H< zh5UllqQsKS{5+u26osPHlG38QVug~7RE6lE)Z&8tyyDbYy~&w;N|Qa=(l@VXvSyxK mz$d-glWiKa4?$Zp^V0H(w_@Vt^-NrwKXF+xZ!X}w#0&r^5=hqo diff --git a/mobile/openapi/lib/api/duplicates_api.dart b/mobile/openapi/lib/api/duplicates_api.dart index d8b45d21a2f88ad2289c16a9cb24cd08d9178f44..9df6e46586debd85aa7d2d308f298b921e2ed6a7 100644 GIT binary patch delta 608 zcmbQC@KkBTCdT@ZjLc$%)V!2}{LH)(g`(8L(#)dNVug~7RE30;(t@1KtUbQb}o19>gGzkdOd{ z=%Cc%g8aPV)L3M#lNYksPOe~++#Ji~#$->SV>ZuWaUKjllHKgXHicr}OrFD{G}(tu uXYxH3(akoTOpIy71y50GVhSZOwYiGRg~=Kiw~+WGm^Lu%+q|16mKgx0Ue87V delta 271 zcmaE=G(%y-CdPn()S|TfqTFJI#5@I$kdOccbr)A3*AQ0){gl#zoXq6JlGI}T>dcf{ zb%p$b)S|?a%=|o{+7yMN)RNMoykdotj8ui_pw!}m{Ji4SSiQ;nIF&a0G1W6oKFTS* zS&vnb(VG}6h&SDDavqc9W&?JArp-q=;}~r)O?P( k7syOF@s$>&&@l1A;%sw(&`u)a3a4X`;>vh)fhZd@0PAKUHvj+t delta 385 zcmdmB^37nw3PzWJ)S|TfqTFJI#5@I$kdOcc^#K3i5C#3T#N^asb%p$b)S|?a%=|o{ ze2PL*YDsBPUa>++Myf(|P-<~OeqM2Etls2$E~U-(OzW8@w{b~Nwr8^0+{UWR=#6Q# zi>r@oh%3}^{p!q=THyPa!cSH#1K+KQE_Jp(ww!Bvl6}n4(aW zT3DJ{lv=D%l98&Akd>dLmt2&ZSdyBcP>@=bn^|0(nV+Y}rJ$g%uMZ&={PIgutrWmE zDHQoVI%u;ln&<)k>X`uq9sX?q delta 248 zcmZ3iv0G)sGDhcs)S|TfqTFJI#5@I$kdOcc^#K3i5C#3L{G?)ah5UllqQsKS{5+s^ zib7FpNoi4Du|i2kszP*7YH>k+UU6!y-eeorpvmibxi(K?3T4{t%o@dLhH0w1D`7)7 tOS0QAZC=Uwo5>y1fPhe_0s7UMDYe8qO?7i5?>DB&&a85qPYOga0|3h6Rq+4- diff --git a/mobile/openapi/lib/api/libraries_api.dart b/mobile/openapi/lib/api/libraries_api.dart index 86acce76b42fa999ee42713c51e4e999aba72df0..9258f8e3eb9c6657d676fd336d577d7911cb0d35 100644 GIT binary patch literal 13643 zcmeHNT~pgQ6n)RHxa~s|cG9HV=|hLMuqlL=8Md$xwzI=9LD&jW*O6RFAK1_E<#MVaSJyhFu!b0p+@$KC?kAq%Lhi zq7fOZZamaoNk0#n#O9m~@OMlk{?$|}G%i(n^FVN=3D;c~Vu!59sI<*hX=f4RRCOc4 zFR+^K6W)FKtQ+)+RFw*Lr$O{U#FUemHSp(ErBVqZq7>}0b4etlsueT%S^=-1c7ml_ z5yJs&0ycC1p02@q_5^Qo|8H(WNPA=$=}ANE3ZTb0iC|KewXkoS=+j< zf5L%;1IC{U9*seYp{8{#3?Xr*0^O%@7TNKS8-b)m(=&*v95AJr;0^2-ExX_FL1>&s z+Y7qBFN_^Ml-!wl-{~B{$stuSdYzv7O%Ep1weFex4NkUfug-_#Z7oj0jUy|8S~~e_ zruEJcJEgDFo;LjYADQmI*E-(iJy9##_N!uN^)(=B%mX`Z=35igu0t$o4{=~2)D0=l zv?Ll`qHqN1WZ-lj5Z%Y=lhvm4BBG#bC#1}nokB!dKq6;m|NIjT5Erpf`mG4ZXsP(| zi7_|(pNCYAtuGZ;ef`(uapUClRc>H?NoIHsA4U;!(R*tnifgxKJauKhXp)rD+4uNSC z25l&4X&Y=c8&K0^B$-A^Vi{9)I5Wz*ju^!5^ci-5X51%Y2!DLc>6aMe1Px7eH?0{* zNqn4|-a!HrJ@EvL%tvTBw)RCj7PLey=9LWwZeZRFn2$qdV3>F0c=7~4eR_5td9%aC zmWv75EgkLgH^s9L4G5}>@PV7E^*uF7WwioC1@E_ZjmZaE1?s@r2M*RGpb=3XYOgv zywbwe?#_1|f|$h}sw4~40#`;0;cuB-nJrQ`S}z-&wE|wq`G(!-X=Z*}?fKmFpyR=6 zSO$*SB)Ywl8Stx=74Bdo6Qzt9Hy5_dhR3dz#H|i6u6ck_gsOjvQGDxGj(2dBF^t0> zaN_^{>oOG(UY2Cug}!0eD`mT>vOU}*{CSkQg{--=j2z~#t6aIJKZ9T`>>Oj>oGjDY$YB#7DTO>VSV$-MJiuf8|0Sr~+3H{i8e(oLu39{J)9RPiHzj$@j| zUWPh;pa(Z@ZWp^gSP1hHX8H>Y4~eE!C7@%LRcF5oi<=wz#Ic7^%7byt=D0SBaq A4*&oF delta 314 zcmX?|bt-Yg2FA$}dWw_X^*kr{vRX`jAi}kI1ydH&1B9r&Zacy2J z?F&=Rw|Rja6UYK}mg3~ZJQTM!DFwrnu}>~g{RvbhEEJ0DOqeV3C-2vS1WLR5bdVm$ J&HJ@_xB#ARaK-=t diff --git a/mobile/openapi/lib/api/map_api.dart b/mobile/openapi/lib/api/map_api.dart index ffe72df453515ded9158a9bdb89f5c4d4237e43d..da4f3dffcc20b0eb36d19d6b09d2fd4c37e333e0 100644 GIT binary patch delta 106 zcmX@FbzW-&KhxwiCa1~#OtF*KF{MmCz^O8MF{kL{Ih9I=x{nQSH-FtJTu$CNTTh*@;<0Zy&S63lXwpKw}lUd7DEIJt-Q v_v9TcS2nk^ePcw^VK@1VAjjl1UZKe)oWf|jb0;@)c}))FGT3~YtAz^y>k}s_ diff --git a/mobile/openapi/lib/api/memories_api.dart b/mobile/openapi/lib/api/memories_api.dart index 9b62cce9c0bbd25c7f3ddf32d1a8e4fdd722e4d8..f9280101e65e45fa07f3acdc0ce8789da1d12eeb 100644 GIT binary patch delta 1705 zcmcJPze~eF9L4ccwG9PPf=GsPROrwlMG76NgB=9vAVE3^MQmxl&_MIU+*SNBbaxQB z`vcsCig=^5qkn=3?mD@-7#p=y^dRkW+xPK4_a5(sJe}U&%nTY`n_zG)-?Lqc132v4 z0T4{PfLjhYUT{()1gOyopiQBLeFz+z5ZiMN72{H=6uo%Iqfo^oH3w+dvqCM}58Oy< zyU{Rla~Fv3xdisdr$Rw#rIy$PLzLGGx?r;hiUiWMXu|KnCQl=sUliv=D|3Z5{zr>9 z!%%)CgtJvCDhqlrg^Yfv%1m1n?+d0BRIC?<)|ocX2TLC^L4~ceCSJM`P&?o%TD#Ml zs49_BjE`>^GpmW~V<&}k`WVqGL~@#SAGK%#b+f^7xQ9hY^7vM e*!Qhzta-E)dzB-8nNh_Zi%M_)&*Q-ChiQY0tB-4lE5Z)_>dcf{ z;w|#o%p@29vcP)s1>xV`nC82?B6)xm!#6vKPGj0EE+NB=C9FZFPW~?=N^Dp+D9qaI zA@hTIbGw2pizKEip`k!R^les96=ViQ-Q-uSQkyhWncXl=Me#eaVG43;iSA40$?Xc0 vHyawAWyTVypri&*6{G|zFwuDclLp&lNhKmlGFr+g4Cki%;I8@5SN02zP>($RPf6$Nwrb{8<(3}l98VRG_0hwC=X(mM@UG3 zLUd4SaY24wacV4F>*R}~T9dQ56*h-6MKd{3?wHBvMRkDYiA~m1Wt+T~Q)sd^pTT4a zE}_X)d`l+3X5}0N{#BS9&*?F_ftzb`IFrz1EiS&v2}(SZ&vKefUZ6C2@^3bt&0E>~ z8L1N%N}J<3`$>r8qSV9`YDckx{^ZM|8k@7YOPL&qj$j-Pfk$tEoX}<+zN<{c$0rUG zDN4OyuPxa8LGT$f#a`QdUNoD9c<+=Jq$JWTJMwQnD#gJ}d=kXz7-)R)Pd+N;zd1n8 lka-Yz5S0ITCf}1{+oW`wgdzu@AC+K6PEs=4tf%V42mrwM+3NrR delta 672 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 diff --git a/mobile/openapi/lib/api/search_api.dart b/mobile/openapi/lib/api/search_api.dart index 1b58702c40dfc727b79bff7e3f97588c628f4213..4d9e1172b8889205c7fbb284c15545e5820e9d0e 100644 GIT binary patch delta 2060 zcmbProN>x|#to|&lR`2wixpDyQVQ}j^GXzoQVUBni&BdfN-|Ov5)zAxQ%m%UQWH}W z6be#{ax;sIGxPKGxD*uh_4Og7f?s|~s+9uRl-$&kjQkX!86~Afc@QH!LP7#2?_yWp z%)_L}WDe8?QAwJ8lMhBJZ}w%;Wu}8;H}7J1A={ywe{-fW*V8^k6{3SuiwpAeic@1z zBO@TOC~@;1-t(-MWIJN>MqWwA&2vS56XTKMlEjkC;*!kdVoDMS4)09f#w)j(Tk;f> zJz>w_b;#t6yvmcgC2c3aS7MuNCNDa9bpq$)2uc3Ui88{(_>$5LfWv?K3ZUqkyoXnO z@>V6Q&2kDgOyox!(2q)+w<>uJxPLassD+7=?~l!aYJMz}Pe;mcmT=JFz?+wVB~mf4 zG@@nfOy12aIayzWeKN0)_2fIT0-ISppD|hCOOE&*1x|@T^EUJP>>u!$0;W6(sON+y z{|^)2oE?xxSqfA}GLC&SUvS7^@T2(V3t_7$^Ow@(3t?uPPe&FE2LDKGUKzWHGXE$~ RUKwi)EDfbLZ%KH@1OO$)yj}nR delta 1028 zcmbPoo^jT3#to|&?E_Ma((;RPixm>{6g)yg0u`OEUBGfXY%7ic(8Ti}H#UN-|P6^DwzEZSG?6Wp==CQffs(PJU4;9-}7nFez`2 z;ZS5^cPj;&pK3F?kymc>9WFcO0Q^Q5m!_wu7K2=e&!q~{L8-+BKsBkcdYc!DNHT6- z&VP_)^9m7ORxIWR_y;3Gp|}L-cc2By#F{^Op@{P2I$7Jz{ZhS5lUInyY_5}SX7?IqzY1tiu3b` z_oMRU3HRN{q{2xvMnbu8E*nc3sHz|vSCudP!*UwHB5MO zdT=npM%l1DW*ty%{*+a^k=d#K&Sz>yKNE2xQa^>OEQZ~GLylkfz(d^t|~FP zo-JT=t@3V0u){#MFH$Y#0GnJ~l3$dV4srTiJtX&W7~Ycust^(m2o1sFQLW9*0f(6; Nw+Hxc{u#{03;^YiX>!2tjLc$%)V!2}{LH)(g`(8L(#)dNVug~7RE31%)Z*gI{5-wnqSVBa z)C7fs)S}!>h!B^8g1){!gjDd$FG;mh0GpJXT9T2U0yL+jv?vc^j7LaFfI@UoYH>k+ zUU6!y9*Wk?h<$T++$OPtK;qp*S-`K;q_aqEnfyiE%#;M*uT{$K*2- qpNYx?r3EQ8%-1H9<78bY`!jKEo+34kxKxDGK|pU=Z;q2qWCj3Cah|UL delta 554 zcmX@^w%>8XI!5<^)S|TfqTFJI#5@I$kdOcc^#K3i5C#3>)Z*gI{Jdgyh5UllqQnv) z8>l2jp(wSav?#Awp(GQ<-KxCVfVYZivN@~FWCLFL$(jOxtuXCy zcO@6G;B3FG#MrN@>YFMq*KFice-($RPf6$Nwrb{8$=dztFZ6UGQfKP~-Sg!$nmO_1x z>FZBcXH(g{O>j4p9g$wc;Siw5v?gy86xzH@Kyk(?|j zsW#a~Qiu&Ksx!G?r)2VB$&-^GN~KJmD;+$!h~>g$1x@S82FiOdH1mT3YjTgQ6siH* zlLOerC&|ew79Q~N`L(&hWE*a-&Hqdm5$#2sjskko17zyv*XD7|09wPW8~^|S delta 429 zcmZpvK3TS5BG=?CjKTu`!66Fz#Tki3sVTZSnR(fh4RpOX>vJDqnp|TjGg+V8c5^?U z7Bf((&}3yv!O4cYfs^Y+g*N92tpur1-dr!r$uhZ*NoI0~q~hcNIgZIwnM7Gj^0QO( zCMR->PW~gQ#*&>{sWVwpN?NQqr!-whA-JR{GcVm<0jx+zp?2~HrSQq?q)tvgtsgqM zTsmd4fVJt>ZwrAIv{8~=d3~0ZV0>}{x1&PJQ z<@rS^R&bV%0!XJ7nACwd$qGVkwv%sVg8EyCr8+aE7U=n;$^KUCo9mPkK%O@Na^yFc zsXm1$6V#Q2shC`+#I;#TGXkcHee)mf_ne^c7IzGB_CN{nVtuID`J307Jp<`*oV?D= OYH~lH#O6FJF=haWn3DVe diff --git a/mobile/openapi/lib/api/stacks_api.dart b/mobile/openapi/lib/api/stacks_api.dart index 6d6c4506be70b141218786433a1f6ef38ca39be3..0f76f3396bd78464a77ce51f5d7c72a7faf2d43a 100644 GIT binary patch delta 1488 zcmZ1xG&f?yD#rSdjLc$%)V!2}{LH)(g`(8L(#)dNVug~7RE31%lEma}z2u_Q#FEqm zg@V+g+|1(Q%=|n(E(HaBeSHY2;Fn*LYNY@+CpWbuBR>UbN=a!^9>frjkdOd{=%Cc% zg8aPV)L2xl0g01Ws!C5j&0;iJL7Z!|KT|xDH3bfuyg*fD^Jx|nW+Hr*lA4oBOJ5mH zwqp|9Je|Xr7$4zu4A4i`K!eyP%X9x61fG(dtii7Xj;ifEVU&7IX|o2uH8BYgnEp~| zl>CYkC$CmD07umi0e2=#!if)uW8e|>mqmDUukcAGB4VqwAcdwGOL6mEu{XrT5>AHz zeWf+|u9)*?eJPc}5L5D#x64Uxz9qejvY67^yj^Z8F@*%qfT2>+R}9We(#ky)#nR>l HsvXP#FCp{q delta 734 zcmbOmu_9>0Dn{3U)S|TfqTFJI#5@I$kdOcc^#K3i5C#3>lEmcfVs(Z5g4CkKlFa-( zpn?>IqSTVoqP${-l8jV^=%Cc%g8aPV)L6aE3QYT%CaW{~Z!TbEV)nr_)5X=tHN+KW zs(y85N-dE_PgY=3nf!oTZt`wk(arXpP9SS!H$UJOXLKiI4e>T8ZSLpo0hug4xt~{O z@;`3D$y){fd16}N?g|eYGCjeyxmd^@>=Qj59DGxik+UU6zHRO{r23YwE2uozBmkmK4M%#_XKLJbFjOx^r|-YZH?OrfIZ z+)9Cd-z+1d#^eADB1o_h7tR0wQVy5{o9kR*;!IS4IyU xQ_@n&Ojd+q3b%uR@uRkRu8aps$*;5^C6NZnFJyCrTn0(W4yQvlKU7F%1OOriD)j&W delta 141 zcmZ4Gam;1IGRDafyg~vlu0F0It_u3am3hhfiOJcM>v%mUN3mLLu4gJ`np`U&y*Y~Y zD<4QHue)mqiaM>$Cq=ZGHk*qZG6Ush*@{bwQWJAQ25kN>H6N^b@_#9#%{p>YAiHFl Rp~i21Ec-?HnHpcppjLc$%)V!2}{LH)(1t2>yPa!cSH#1K+KQE_Jp(ww!Bvl6}n4(aW zT3DJ{lv=D%l98&AP+VDDlA7zBpO==Iu2+4!6u=hcrj}&ngN!OEEy@F##Fnby5fTzGIe=YrvmBEsQxs4eL@CwXwAp~=2Gbz% z@8$q@e_Hx=vH^?g=7XGv2aA7!@vFS~KaUG7{k++M-<+8`@mpGul30>TPKuTSWe!k^ rR)`KtEiTBO8`6lOcgiSsvYQ340vy5?apoHY+_bhvu zJcuz}KP5FSu{5Wo7>_lZ4LJOnK*mmf&%(L+AJ<_fG3-W9zRIT|h1a>tn=|=bKxPSV qmK9WF_Qo_PAe4jvP>2pnEiTBYF$w*a5D6T9nNzL_5ElEsCEJ@TWN=-~jP$)<(%FQe;&dkr#<5E!2*Vl)T z3V!(|sa6VLt8!CIGV(!&m6R6c6)SLn4D$#H37CA4U3s%UlQ~m5P#Z)kZCvG63bZ-Z z#&NQuxcKH)md8wkCI~hkWKU;`p{4gXt8!^F4;uf1qx=}J4UPT$pI?+}el9HlruJ0Q v6S@o}*MJhbLUd4SaY24wacV3ylT2c delta 288 zcmZoO-Dt337o%7}YEfE#QEst9VxEFWNJxN!y1Q$L!sL@oN>U2>1*t`eC7JnoK*HQXLihz?3EF38U-PL0*uoG2>FJUK%&d9#D08zTS#R$m(c diff --git a/mobile/openapi/lib/api/tags_api.dart b/mobile/openapi/lib/api/tags_api.dart index f6cfc8720bead21161bd1bd6134bd233a8539c86..a0cdb91acfd1e8e6fdece7f6c245ac7b36b14fce 100644 GIT binary patch literal 15729 zcmeHN(Q?x`6n)QE2p&kflTBD=AD9B|rfmwH>C!Hw!|ZfAL5-C};K)W&2wA58zE_fE zOR1f-Bq>et10}MhD_J_{9^ET7o0Vo0waz*xzrSw3ZNF=E+6Uk`ZCDZp(BOM_lH% zz~KZ>MK>PHE+=2cltXidNANes9R8Pt3oy<_e)C?$gv3mCX#gG4J|$c?7rC8?`O|K1h`Fd#pgW18K8j+(a7-KU??t6j>4jJb)WHMMiYfYDLH2j;93Je4 z6uR9-P}%&v*h1S`3B7WD@9v_2^zk^9X+!7$p+03eMCr4vg?`(FY3>ZEK!gQxM43d% zGzlb!1bviv(0~yV`4Pp0kEjqdVhu104b5NlHj=P3+6c_&Fbcqg9CKzYyyxabB1mXBizQzBplcCKNy zPO%)q>hNk4MlG6p21QlRc%C`EMgW{14vnFc%TJ^S3m->9?nS{AY|VatV$3Y>moec} zJ(~imzWgUG?wnt|aE3M{I3PT$_+E0#26bfq-}!#!RtDaU=2q2)^;97ED*>vVX-xD8 z5`*Ve9LFK;={ahC5)rGycoZyAf|3l64a&YopGoWVsHWc|^-4`-Jt6sq0tT&t1|GyMCxAw~ zGrYJp7YyEb!e`}yCYZ`OWShlpT~8fCw66$k+(HAKtQ?E|C?II(6;ecfub(t7aqtfO zHW6|wAtM6E#G{GwXzg!35-axQ8LB5EQ!E9$ibZ=7TnG57)!C>O0-QwD1G*qS~Bl46<8 z1e&OikbJ7`M|Lb=iD+O8O?WdfZw1uH0sO(48wNai0-t_;bsl-E!=in|`)qNH?@#6) z2yAq#5fGS9ibMJzX(`WIGq5RMoI0u&VYsT@vl7Zo4;+Xa7pCXOENwC*#pqkHw#NyU z{nE_llL1cZ3cA3B$=;m>6+{9 zU0TXVIw0GjIVhRw8y+ha%NoxCd4YPRhCJr@c8pu`d}gUyrE2+G3Zq&MN;9o;9w=e|T3{_epx;khdw>$0446qgvVU7wdLi5*%1`d*IMd&S%mV62* z?B7E{xp6=X8`Pj!^KYFIx|X{c5DCNu$00n=vD&oE5(qqF)xHt!*yb@HK1Ypfux;bS35$u7!a7(}F*&LrnCCn>^{ zjEk}lTgg1YRux8(db5@6bYQR3!`G2rbKc8HHK+|BZ-y_`K}sJI&BShomdldl5pLaw z1B*1xh-tcAo&k4|nWkm~1bw+l$%v_d2&hXz}^?(yHttT;GgKA)Zej zsPDwc5F)1>a^={y>S1q&H@@3V!{pSa$4eC^yErZbjjwk*pj~e=*ZYUiKJsiJLK2){=phvbH(0 zwumGvM0(!M1}$3__UcCWnI-{nXCBlG#mZXp)Ji&5OQm|yO63FNE>pSyUF*pKygSAD N+?k3?Cv&eV{{su*3HSg2 delta 837 zcmexZwXb-?GDgpU)S|TfqTFJI#5@I$kdOcc^?=Y21^tr5^kV(Q;^NejVs(Z5g4CkK zlFa-(prRCoqSTVoqP${-l8jV^=%Cc%g8aPV)L6aA3an9+CuneOu4T$*+N{o6&g_iE zZ2w@W;l!J&y4jqwhiS4ptK4LBPTkFZJfE1nFim!G^>Gbxg*v=CGo_YD3ns}rfn2>w zz>{e*yR7x(BSK%zFim%NCG70Yk|JhIlZCA0HZK*EXLiS9h(77=+uS7O&a|0bR+QNf z(_lo5fea=w+CCV0Ocqel0Y@FLVl&g^??#TB1yp7-2Vz=;5y<4(wRwWZB(Oa|i`_QA z&<@8ITBx2PGBziFFscChgnP4@K_k=V??y$;PME%cn@p^s3aqM=-&pE`4Yo250jI^y IZ!BAx0hH(@oB#j- diff --git a/mobile/openapi/lib/api/timeline_api.dart b/mobile/openapi/lib/api/timeline_api.dart index 2d3ced610b9103acda7b338ea8dd5343f9c554c7..2d142e3d674da8a71a4594d68210bfb91ed5d580 100644 GIT binary patch delta 430 zcmeB;y%o1%9bYFk+ zUU6zHs@8zSqQuSL`ChVYe$U3jVM(@2HoxIJ$vMy-nf#qke)9r;2bRh2*~BMr*W%ke WNw$NXd{0e&!>0u{Z*#4t04o5S{gZ+K delta 201 zcmcZ=*BiTG9iwkRYEfE#QEst9VxEFWNJxN!y1Q$Lf__P6ZfZ_uUaEdlX>xXIiMm35 zL26NANoIZ?P+^KfQEEwPQC_h^Nk*zdbWmz>L4ICwYOLPm36ffyYxz&HO#US+zFC+3 gE&Jr@lFC4l`J8^lSyW7jLc$%)V!2}{LH)(g`(8L(#)dNVug~7RE31Z;^Nd2y_D3P)RNQ$ zg@V+g+|1(Q%=|n(E(HaBeSHY2;Fn*LYNY@+CpWbuBR>UbN=a!^9>frjkdT1My}SyW z*_h;*EP=WpDoM3*vm(n~rh0lfRv|hlwYVTZuQ)Xp)t>>0o1@q_F{<8;*$KLRQ<%_;?$C2 zJfl?8J;FI0aqLFh9WlQhGPtZk zHl=Zl$?rXeUDyV!sDGYpz-IadZ>`_k+u+gx8GFK1#Kr&y%qJe0w6uoGZQ+!6hl~UD z-7sLj0Q^mSAhKi61K*oM6pRIRFwup0Iys0Tg;P~V4x`zRC=v7&LK=-2=PdA>*fPr2 zf8lc=a3xhcIQ_#wN)qG9*MdHFy9aQ5NO_1ePfxN{56qHnW<>r1$FgZPf$vrGJ0ds% z)RkNsG!iA)kP>#s*f4#Qw6+Dh??%>FCWaq{2>1L!&@ic{g@Oj04Iq5#_thH8QO7#G z31LJBs1-_~dM?FvkBGp@;n+;GjjF26b7FB}PWB~pZsM+0VNL3GFfyZ?ch92vyS!#XbfnUe|NG*m~V^Z~PGXEm@ zhqe#)8Y&-TmYhl_{;VJDf9ckfFKft2QZir3w>{bm>2QG!Jw;;j&MWr;)hnqh7zqsg3uhQ-bqxW zT#34OQ$e{YyAgNfN+~1Sgs(%2Ru#2)gtib6;TJSAR?rXNOaga;#s>@O4ol{E`QkSR zCRlz*P`&&>ppBOe0u$0qD)Z15${Y(eqO!^)Vgf;mX^cB?D%o`twGx{Xr`Q0B(L+Qd z|MbYGKSHz})Rp#M)@DA^=F>#9m}kM92{Z= zX+Xo}*)tsa?CLzptd1YN*H$839L*Z>+#}pIDK=e-^T~+E{-teci5rU+$ANm0CfAiI zS3InE#Zq!@=+wOEC5^ixVSmTac5$n-elpb-_ym}nBg~Y=ZOYwIoy=0MNy|x?p|04W<*1e^l97k8g-T7VE+){2~6~!)$sj| z2-*zfe@M_foll)^=dn_>*7EtA;u4BpJs1u6EE|VJuKR2<8@EK`98S-*lEJ?Oei6#G z0nV^W#p@NXXE$Bdvj6Y`EAar z_=|CN#ylpbCvahY7haUcdt7;U!nk1lQkI2FywM1}ZL5QhNr`*pK&}hhRu>$&%I>`H z=w4NwH(SzmqzCcniCVhMQY`_zW07|j>79yoG1?@qE1lduE3HwlqgN#rfM4lH_LfVx z6ff@54aN0UJMr(?W>QsMvYk`_Hk5v(Eh*nV`qwyKLC(3Xu8!>(S~C+1Qf@Jq+2s5T zv!^VRGnQZq3`d86P}aQ-Q&c#y^=kTdl=|5%=KHZ;Dn%?2kF-Y!Q5x z;r4Qud>#-M&t?w?b2u_zKLe=BSy4GFZsM%ShlE*fihR}@IjwxVy=q3AaVlu1!vy0P zcT|L!ay!fr9j7Gf4<*kPI1w)6@M82G;Qm#65iEhLatz!e;QGG!~&8zS7339>!6;7znzBr{g@X z8#l%B93Ich{c1nbK&8baESd^Su{Q0G>h$`!qr$UF6Tg626aua(+B_?XL&i&D%5g8L z-X}@<=njL;@O&J) zKj9VE+z_>l+s{~>Bh|@l;JHa#6nL&jXk=x~NP50b1J6^zW8AB#U7ksL=z-^EAopeW zQhp}C+m~TSk2Y#ftN8pl(`)SrayYs(BpT#d`v%-L=sufF>y*C~6tjF_UXtZn$$(#O zABrHZSwilD6Z2oaCaYeP<(~T8>!|ZZ_F&Z>f<>mpitsqfQhQNOPTGuPA;q{=Tk&=V z?m4cv%9=hXb5NAALf&6X0Ac((yl80EP9S*|pF|fvC|DPaeZfTGO1M8-txWMB3 HhO63tES8bm delta 957 zcmbQy&v>Poal{lt{q%slSh-sONtB-4lD~fgc)tM=^#M`MencqQSavrY**iL1xB_KOh zL4up}cr%&(Fzs}AMfD%a7Ru|0ZC)!F1+hq8M|bi)752>sL@qIjVYh6umZO{+(SfKl z8E8JxGlH8dB@$qENNui=7GaLWZa#8kfjy&NTmp=);*!i{5+V;2kTR1SR5&&l$osKC z0}(7Rxj;UC^D&jl%;K2#gHy}o)tXYIdys3hwPq~XgPY}b_?SI04M&eDB2&fYgZeql zKo10MzHdAeTM7sWr7#76QdgA4V|Y@V9A#lK`7W#YWPcZ~&9*iI%ve$a$Wjth!e)L4 U3y?=Z$vI_miL~rye-}??0B(LzwEzGB diff --git a/mobile/openapi/lib/api/users_api.dart b/mobile/openapi/lib/api/users_api.dart index cd31617e74cfc65eaa12d5707d25e923a18ced7c..c8891ba0c22cd0bde396b4c22eb8cc173fc721f6 100644 GIT binary patch literal 23615 zcmeHPU2oeq6n*!v;QBB-gKKxi9)`3{mNw27tZlN^!7v1Y%UE>GO%_#=ZsryF@4Nhv zNXn9})M^^HdT1I+g4eF=&$b}nN0ahfD`fTaqq{UTk?@!MJyqs2}?#38j@W!kLH{NBNCDsi9|Pjrn8tO zqA&*zuknJ9;<*?l`^i>@GJ@{(#P3L9?jr#3QK41+*z7sFM!qj!b?u zhf>JX)bt)2Cj=_$*8NW^roRahA4e0`@hmEX-5rGaA{whM0IoJ^dql+&jN`;?!qKZ~#LmyHq87D-s%Ab&>vm@8gY|7<_ED zGO04G+K=F;08kDWF>wsUIk$YQhR*fP@*1BS=*Yu4$dOgYqvsf(9zUn$) z7VoR#MV(KzUA3fkzEH4JMEvPa|6h*J@|J_V#zeXb(%6ALtRrP$w**V zGR5GalF@U-&?T5a*T9mHNLN^D*5gM%bB5eW8!)btUM2^LvTpljI(kt~#bmevI<5rt*0curSLdTG{ivT=ZT z&?gQ0@4ttpFLf#c9&tt|VlOn^*}+LYS-}CERts}4Akd!_hx9*kAXTKJ@lrlGUDRHQ z+qTjpv@(sR7}ZmHkWJ+z6UuL&=CT3Iuxgd~C2iIvlxlM$#HE_8#u{9S0~M7BvD93Z zEJbRD(Y2a$ICwc24%(?$Y_IARL)hT(1Eawn5Qjv$i@}bMyAlOh&gac5?<4tFrh%7q zOkiFPWOg?UAXh%7OurLro{7&$Kh#b8>Zjq~sQ0f%Zh_-F(7TP_JK221YAN<+9AA3Q zSJ~}PqDzL80A^Ho>iM=5w8}uJnna5{S=`0@MP0?!vW&bw&0!C_&!+)f~O)eO3X1LH@afrv{APhTgnG8bB zG=ME!^?msSz*iEg-(Zh$i`NIvA(qvP+Z7?{bx_X^FdRW37$VO(z<0_(UJ`4_W%v9= zI!Yr=jWkt}CJ&ZIle~AeiP8NRprr|3nNKd$zlyuw;sBUZltyY)58OT&y|q%a#s@Z# z7m3}aC60Xg3Bt1E2aTXKCzq<8T*?8_S>`zKtW8wX;O^>a+pSL?7sVuG!to0iCXC->M|G& zr7wS|jn!=cea(caHe$CW`d(6d0HV*D11Dnr6^E^*cMGIK=o*H%sR~Kne!dmY+iX6F zo4ufBFR031kj0OKO2hVr-)bZLLSNY+II%Q;=L9F?shkXb*5gD?c=;O(FTbQ*Je9C= zJZ2AO>ki(kQMi+#A@6VI#+V=6k@xhn>xAXk!!+w6b3G3kW?ymNEHP)(L3pfFI zfkJ&pL_e;JWpg6RmffCN-)il_?OLw303N-zZ^?~w9LG>?brrw=H)oN$ZvKhUhSRex zJ@{(Cw)PJ*tOz@Jc&+3HCWoVkN)BC*=y+CreC52rC&-K(S9n z+dJLn`Z6MC7j;VHShh6`NL~8p zWYTLN_xBHrSiEhbcGgN&f3P_U1)JAzi0 zRl1SQ?U7B3|Fuqd2cDGk4~LOp30dG=om_^@g-fxSbEp!fEhx&<+A`!fvfIdRHQCJp z*Fn0`-tq+X#oRQ^YrM%{S$4Ifz9O00Ixnh$ RlJd}XR4)H%y}sSF{s)Crf2;ri delta 1291 zcmdnLgYoKW#tkbNg91{E((;RPixm>{6g)yg0uP25QWKw{$luzQr)a1rp`2(KS*Ws28jnuR@lvf##t^tUvB;=ZOODbS?&oFF2^(~ zNvYxX7g|I+fg@Q+DVk~X4iy<}5e)Jm)M3?`DYbYa0ISiHHC&m1>Bo9=koI*ZCj$N^ zB9=E#)N^B+e8pL2v$5eBoMAv9ZYS!gPYyGen0!_*XmWsu>t+YjGRDb=yyQ1anBQPB z$LB~q-rpQ(Wx=%hkc|_wAEpTbq3}>7DlwylrPAb;&PL##V&-%&ADm_a(>MucPCggtvH6VO9EiE+0;e&%5eO7KA&VXun}3Hc Lff)Qd!i5(`/map/markers${QS.query(QS.explode({ - fileCreatedAfter, - fileCreatedBefore, isArchived, isFavorite, + fileCreatedAfter, + fileCreatedBefore, withPartners, withSharedAlbums }))}`, { @@ -2542,6 +2725,9 @@ export function reverseGeocode({ lat, lon }: { ...opts })); } +/** + * This endpoint requires the `memory.read` permission. + */ export function searchMemories({ $for, isSaved, isTrashed, $type }: { $for?: string; isSaved?: boolean; @@ -2560,6 +2746,9 @@ export function searchMemories({ $for, isSaved, isTrashed, $type }: { ...opts })); } +/** + * This endpoint requires the `memory.create` permission. + */ export function createMemory({ memoryCreateDto }: { memoryCreateDto: MemoryCreateDto; }, opts?: Oazapfts.RequestOpts) { @@ -2572,6 +2761,9 @@ export function createMemory({ memoryCreateDto }: { body: memoryCreateDto }))); } +/** + * This endpoint requires the `memory.statistics` permission. + */ export function memoriesStatistics({ $for, isSaved, isTrashed, $type }: { $for?: string; isSaved?: boolean; @@ -2590,6 +2782,9 @@ export function memoriesStatistics({ $for, isSaved, isTrashed, $type }: { ...opts })); } +/** + * This endpoint requires the `memory.delete` permission. + */ export function deleteMemory({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2598,6 +2793,9 @@ export function deleteMemory({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `memory.read` permission. + */ export function getMemory({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2608,6 +2806,9 @@ export function getMemory({ id }: { ...opts })); } +/** + * This endpoint requires the `memory.update` permission. + */ export function updateMemory({ id, memoryUpdateDto }: { id: string; memoryUpdateDto: MemoryUpdateDto; @@ -2621,6 +2822,9 @@ export function updateMemory({ id, memoryUpdateDto }: { body: memoryUpdateDto }))); } +/** + * This endpoint requires the `memoryAsset.delete` permission. + */ export function removeMemoryAssets({ id, bulkIdsDto }: { id: string; bulkIdsDto: BulkIdsDto; @@ -2634,6 +2838,9 @@ export function removeMemoryAssets({ id, bulkIdsDto }: { body: bulkIdsDto }))); } +/** + * This endpoint requires the `memoryAsset.create` permission. + */ export function addMemoryAssets({ id, bulkIdsDto }: { id: string; bulkIdsDto: BulkIdsDto; @@ -2647,6 +2854,9 @@ export function addMemoryAssets({ id, bulkIdsDto }: { body: bulkIdsDto }))); } +/** + * This endpoint requires the `notification.delete` permission. + */ export function deleteNotifications({ notificationDeleteAllDto }: { notificationDeleteAllDto: NotificationDeleteAllDto; }, opts?: Oazapfts.RequestOpts) { @@ -2656,6 +2866,9 @@ export function deleteNotifications({ notificationDeleteAllDto }: { body: notificationDeleteAllDto }))); } +/** + * This endpoint requires the `notification.read` permission. + */ export function getNotifications({ id, level, $type, unread }: { id?: string; level?: NotificationLevel; @@ -2674,6 +2887,9 @@ export function getNotifications({ id, level, $type, unread }: { ...opts })); } +/** + * This endpoint requires the `notification.update` permission. + */ export function updateNotifications({ notificationUpdateAllDto }: { notificationUpdateAllDto: NotificationUpdateAllDto; }, opts?: Oazapfts.RequestOpts) { @@ -2683,6 +2899,9 @@ export function updateNotifications({ notificationUpdateAllDto }: { body: notificationUpdateAllDto }))); } +/** + * This endpoint requires the `notification.delete` permission. + */ export function deleteNotification({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2691,6 +2910,9 @@ export function deleteNotification({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `notification.read` permission. + */ export function getNotification({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2701,6 +2923,9 @@ export function getNotification({ id }: { ...opts })); } +/** + * This endpoint requires the `notification.update` permission. + */ export function updateNotification({ id, notificationUpdateDto }: { id: string; notificationUpdateDto: NotificationUpdateDto; @@ -2764,6 +2989,9 @@ export function unlinkOAuthAccount(opts?: Oazapfts.RequestOpts) { method: "POST" })); } +/** + * This endpoint requires the `partner.read` permission. + */ export function getPartners({ direction }: { direction: PartnerDirection; }, opts?: Oazapfts.RequestOpts) { @@ -2776,6 +3004,9 @@ export function getPartners({ direction }: { ...opts })); } +/** + * This endpoint requires the `partner.delete` permission. + */ export function removePartner({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2784,6 +3015,9 @@ export function removePartner({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `partner.create` permission. + */ export function createPartner({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2795,6 +3029,9 @@ export function createPartner({ id }: { method: "POST" })); } +/** + * This endpoint requires the `partner.update` permission. + */ export function updatePartner({ id, updatePartnerDto }: { id: string; updatePartnerDto: UpdatePartnerDto; @@ -2808,6 +3045,9 @@ export function updatePartner({ id, updatePartnerDto }: { body: updatePartnerDto }))); } +/** + * This endpoint requires the `person.delete` permission. + */ export function deletePeople({ bulkIdsDto }: { bulkIdsDto: BulkIdsDto; }, opts?: Oazapfts.RequestOpts) { @@ -2817,6 +3057,9 @@ export function deletePeople({ bulkIdsDto }: { body: bulkIdsDto }))); } +/** + * This endpoint requires the `person.read` permission. + */ export function getAllPeople({ closestAssetId, closestPersonId, page, size, withHidden }: { closestAssetId?: string; closestPersonId?: string; @@ -2837,6 +3080,9 @@ export function getAllPeople({ closestAssetId, closestPersonId, page, size, with ...opts })); } +/** + * This endpoint requires the `person.create` permission. + */ export function createPerson({ personCreateDto }: { personCreateDto: PersonCreateDto; }, opts?: Oazapfts.RequestOpts) { @@ -2849,6 +3095,9 @@ export function createPerson({ personCreateDto }: { body: personCreateDto }))); } +/** + * This endpoint requires the `person.update` permission. + */ export function updatePeople({ peopleUpdateDto }: { peopleUpdateDto: PeopleUpdateDto; }, opts?: Oazapfts.RequestOpts) { @@ -2861,6 +3110,9 @@ export function updatePeople({ peopleUpdateDto }: { body: peopleUpdateDto }))); } +/** + * This endpoint requires the `person.delete` permission. + */ export function deletePerson({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2869,6 +3121,9 @@ export function deletePerson({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `person.read` permission. + */ export function getPerson({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2879,6 +3134,9 @@ export function getPerson({ id }: { ...opts })); } +/** + * This endpoint requires the `person.update` permission. + */ export function updatePerson({ id, personUpdateDto }: { id: string; personUpdateDto: PersonUpdateDto; @@ -2892,6 +3150,9 @@ export function updatePerson({ id, personUpdateDto }: { body: personUpdateDto }))); } +/** + * This endpoint requires the `person.merge` permission. + */ export function mergePerson({ id, mergePersonDto }: { id: string; mergePersonDto: MergePersonDto; @@ -2905,6 +3166,9 @@ export function mergePerson({ id, mergePersonDto }: { body: mergePersonDto }))); } +/** + * This endpoint requires the `person.reassign` permission. + */ export function reassignFaces({ id, assetFaceUpdateDto }: { id: string; assetFaceUpdateDto: AssetFaceUpdateDto; @@ -2918,6 +3182,9 @@ export function reassignFaces({ id, assetFaceUpdateDto }: { body: assetFaceUpdateDto }))); } +/** + * This endpoint requires the `person.statistics` permission. + */ export function getPersonStatistics({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2928,6 +3195,9 @@ export function getPersonStatistics({ id }: { ...opts })); } +/** + * This endpoint requires the `person.read` permission. + */ export function getPersonThumbnail({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -2938,6 +3208,9 @@ export function getPersonThumbnail({ id }: { ...opts })); } +/** + * This endpoint requires the `asset.read` permission. + */ export function getAssetsByCity(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -2946,6 +3219,9 @@ export function getAssetsByCity(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `asset.read` permission. + */ export function getExploreData(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -2954,6 +3230,9 @@ export function getExploreData(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `asset.read` permission. + */ export function searchLargeAssets({ albumIds, city, country, createdAfter, createdBefore, deviceId, isEncoded, isFavorite, isMotion, isNotInAlbum, isOffline, lensModel, libraryId, make, minFileSize, model, personIds, rating, size, state, tagIds, takenAfter, takenBefore, trashedAfter, trashedBefore, $type, updatedAfter, updatedBefore, visibility, withDeleted, withExif }: { albumIds?: string[]; city?: string | null; @@ -3027,6 +3306,9 @@ export function searchLargeAssets({ albumIds, city, country, createdAfter, creat method: "POST" })); } +/** + * This endpoint requires the `asset.read` permission. + */ export function searchAssets({ metadataSearchDto }: { metadataSearchDto: MetadataSearchDto; }, opts?: Oazapfts.RequestOpts) { @@ -3039,6 +3321,9 @@ export function searchAssets({ metadataSearchDto }: { body: metadataSearchDto }))); } +/** + * This endpoint requires the `person.read` permission. + */ export function searchPerson({ name, withHidden }: { name: string; withHidden?: boolean; @@ -3053,6 +3338,9 @@ export function searchPerson({ name, withHidden }: { ...opts })); } +/** + * This endpoint requires the `asset.read` permission. + */ export function searchPlaces({ name }: { name: string; }, opts?: Oazapfts.RequestOpts) { @@ -3065,6 +3353,9 @@ export function searchPlaces({ name }: { ...opts })); } +/** + * This endpoint requires the `asset.read` permission. + */ export function searchRandom({ randomSearchDto }: { randomSearchDto: RandomSearchDto; }, opts?: Oazapfts.RequestOpts) { @@ -3077,6 +3368,9 @@ export function searchRandom({ randomSearchDto }: { body: randomSearchDto }))); } +/** + * This endpoint requires the `asset.read` permission. + */ export function searchSmart({ smartSearchDto }: { smartSearchDto: SmartSearchDto; }, opts?: Oazapfts.RequestOpts) { @@ -3089,6 +3383,9 @@ export function searchSmart({ smartSearchDto }: { body: smartSearchDto }))); } +/** + * This endpoint requires the `asset.statistics` permission. + */ export function searchAssetStatistics({ statisticsSearchDto }: { statisticsSearchDto: StatisticsSearchDto; }, opts?: Oazapfts.RequestOpts) { @@ -3101,6 +3398,9 @@ export function searchAssetStatistics({ statisticsSearchDto }: { body: statisticsSearchDto }))); } +/** + * This endpoint requires the `asset.read` permission. + */ export function getSearchSuggestions({ country, includeNull, make, model, state, $type }: { country?: string; includeNull?: boolean; @@ -3123,6 +3423,9 @@ export function getSearchSuggestions({ country, includeNull, make, model, state, ...opts })); } +/** + * This endpoint requires the `server.about` permission. + */ export function getAboutInfo(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3131,6 +3434,9 @@ export function getAboutInfo(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `server.apkLinks` permission. + */ export function getApkLinks(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3155,12 +3461,18 @@ export function getServerFeatures(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `serverLicense.delete` permission. + */ export function deleteServerLicense(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchText("/server/license", { ...opts, method: "DELETE" })); } +/** + * This endpoint is an admin-only route, and requires the `serverLicense.read` permission. + */ export function getServerLicense(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3171,6 +3483,9 @@ export function getServerLicense(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `serverLicense.update` permission. + */ export function setServerLicense({ licenseKeyDto }: { licenseKeyDto: LicenseKeyDto; }, opts?: Oazapfts.RequestOpts) { @@ -3199,6 +3514,9 @@ export function pingServer(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `server.statistics` permission. + */ export function getServerStatistics(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3207,6 +3525,9 @@ export function getServerStatistics(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `server.storage` permission. + */ export function getStorage(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3247,12 +3568,18 @@ export function getVersionHistory(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `session.delete` permission. + */ export function deleteAllSessions(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchText("/sessions", { ...opts, method: "DELETE" })); } +/** + * This endpoint requires the `session.read` permission. + */ export function getSessions(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3261,6 +3588,9 @@ export function getSessions(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `session.create` permission. + */ export function createSession({ sessionCreateDto }: { sessionCreateDto: SessionCreateDto; }, opts?: Oazapfts.RequestOpts) { @@ -3273,6 +3603,9 @@ export function createSession({ sessionCreateDto }: { body: sessionCreateDto }))); } +/** + * This endpoint requires the `session.delete` permission. + */ export function deleteSession({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3281,6 +3614,9 @@ export function deleteSession({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `session.update` permission. + */ export function updateSession({ id, sessionUpdateDto }: { id: string; sessionUpdateDto: SessionUpdateDto; @@ -3294,6 +3630,9 @@ export function updateSession({ id, sessionUpdateDto }: { body: sessionUpdateDto }))); } +/** + * This endpoint requires the `session.lock` permission. + */ export function lockSession({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3302,6 +3641,9 @@ export function lockSession({ id }: { method: "POST" })); } +/** + * This endpoint requires the `sharedLink.read` permission. + */ export function getAllSharedLinks({ albumId }: { albumId?: string; }, opts?: Oazapfts.RequestOpts) { @@ -3314,6 +3656,9 @@ export function getAllSharedLinks({ albumId }: { ...opts })); } +/** + * This endpoint requires the `sharedLink.create` permission. + */ export function createSharedLink({ sharedLinkCreateDto }: { sharedLinkCreateDto: SharedLinkCreateDto; }, opts?: Oazapfts.RequestOpts) { @@ -3326,24 +3671,27 @@ export function createSharedLink({ sharedLinkCreateDto }: { body: sharedLinkCreateDto }))); } -export function getMySharedLink({ key, password, slug, token }: { - key?: string; +export function getMySharedLink({ password, token, key, slug }: { password?: string; - slug?: string; token?: string; + key?: string; + slug?: string; }, opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; data: SharedLinkResponseDto; }>(`/shared-links/me${QS.query(QS.explode({ - key, password, - slug, - token + token, + key, + slug }))}`, { ...opts })); } +/** + * This endpoint requires the `sharedLink.delete` permission. + */ export function removeSharedLink({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3352,6 +3700,9 @@ export function removeSharedLink({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `sharedLink.read` permission. + */ export function getSharedLinkById({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3362,6 +3713,9 @@ export function getSharedLinkById({ id }: { ...opts })); } +/** + * This endpoint requires the `sharedLink.update` permission. + */ export function updateSharedLink({ id, sharedLinkEditDto }: { id: string; sharedLinkEditDto: SharedLinkEditDto; @@ -3411,6 +3765,9 @@ export function addSharedLinkAssets({ id, key, slug, assetIdsDto }: { body: assetIdsDto }))); } +/** + * This endpoint requires the `stack.delete` permission. + */ export function deleteStacks({ bulkIdsDto }: { bulkIdsDto: BulkIdsDto; }, opts?: Oazapfts.RequestOpts) { @@ -3420,6 +3777,9 @@ export function deleteStacks({ bulkIdsDto }: { body: bulkIdsDto }))); } +/** + * This endpoint requires the `stack.read` permission. + */ export function searchStacks({ primaryAssetId }: { primaryAssetId?: string; }, opts?: Oazapfts.RequestOpts) { @@ -3432,6 +3792,9 @@ export function searchStacks({ primaryAssetId }: { ...opts })); } +/** + * This endpoint requires the `stack.create` permission. + */ export function createStack({ stackCreateDto }: { stackCreateDto: StackCreateDto; }, opts?: Oazapfts.RequestOpts) { @@ -3444,6 +3807,9 @@ export function createStack({ stackCreateDto }: { body: stackCreateDto }))); } +/** + * This endpoint requires the `stack.delete` permission. + */ export function deleteStack({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3452,6 +3818,9 @@ export function deleteStack({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `stack.read` permission. + */ export function getStack({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3462,6 +3831,9 @@ export function getStack({ id }: { ...opts })); } +/** + * This endpoint requires the `stack.update` permission. + */ export function updateStack({ id, stackUpdateDto }: { id: string; stackUpdateDto: StackUpdateDto; @@ -3475,6 +3847,9 @@ export function updateStack({ id, stackUpdateDto }: { body: stackUpdateDto }))); } +/** + * This endpoint requires the `stack.update` permission. + */ export function removeAssetFromStack({ assetId, id }: { assetId: string; id: string; @@ -3484,6 +3859,9 @@ export function removeAssetFromStack({ assetId, id }: { method: "DELETE" })); } +/** + * This endpoint requires the `syncCheckpoint.delete` permission. + */ export function deleteSyncAck({ syncAckDeleteDto }: { syncAckDeleteDto: SyncAckDeleteDto; }, opts?: Oazapfts.RequestOpts) { @@ -3493,6 +3871,9 @@ export function deleteSyncAck({ syncAckDeleteDto }: { body: syncAckDeleteDto }))); } +/** + * This endpoint requires the `syncCheckpoint.read` permission. + */ export function getSyncAck(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3501,6 +3882,9 @@ export function getSyncAck(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `syncCheckpoint.update` permission. + */ export function sendSyncAck({ syncAckSetDto }: { syncAckSetDto: SyncAckSetDto; }, opts?: Oazapfts.RequestOpts) { @@ -3534,6 +3918,9 @@ export function getFullSyncForUser({ assetFullSyncDto }: { body: assetFullSyncDto }))); } +/** + * This endpoint requires the `sync.stream` permission. + */ export function getSyncStream({ syncStreamDto }: { syncStreamDto: SyncStreamDto; }, opts?: Oazapfts.RequestOpts) { @@ -3543,6 +3930,9 @@ export function getSyncStream({ syncStreamDto }: { body: syncStreamDto }))); } +/** + * This endpoint is an admin-only route, and requires the `systemConfig.read` permission. + */ export function getConfig(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3551,6 +3941,9 @@ export function getConfig(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `systemConfig.update` permission. + */ export function updateConfig({ systemConfigDto }: { systemConfigDto: SystemConfigDto; }, opts?: Oazapfts.RequestOpts) { @@ -3563,6 +3956,9 @@ export function updateConfig({ systemConfigDto }: { body: systemConfigDto }))); } +/** + * This endpoint is an admin-only route, and requires the `systemConfig.read` permission. + */ export function getConfigDefaults(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3571,6 +3967,9 @@ export function getConfigDefaults(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `systemConfig.read` permission. + */ export function getStorageTemplateOptions(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3579,6 +3978,9 @@ export function getStorageTemplateOptions(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `systemMetadata.read` permission. + */ export function getAdminOnboarding(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3587,6 +3989,9 @@ export function getAdminOnboarding(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `systemMetadata.update` permission. + */ export function updateAdminOnboarding({ adminOnboardingUpdateDto }: { adminOnboardingUpdateDto: AdminOnboardingUpdateDto; }, opts?: Oazapfts.RequestOpts) { @@ -3596,6 +4001,9 @@ export function updateAdminOnboarding({ adminOnboardingUpdateDto }: { body: adminOnboardingUpdateDto }))); } +/** + * This endpoint is an admin-only route, and requires the `systemMetadata.read` permission. + */ export function getReverseGeocodingState(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3604,6 +4012,9 @@ export function getReverseGeocodingState(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint is an admin-only route, and requires the `systemMetadata.read` permission. + */ export function getVersionCheckState(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3612,6 +4023,9 @@ export function getVersionCheckState(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `tag.read` permission. + */ export function getAllTags(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3620,6 +4034,9 @@ export function getAllTags(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `tag.create` permission. + */ export function createTag({ tagCreateDto }: { tagCreateDto: TagCreateDto; }, opts?: Oazapfts.RequestOpts) { @@ -3632,6 +4049,9 @@ export function createTag({ tagCreateDto }: { body: tagCreateDto }))); } +/** + * This endpoint requires the `tag.create` permission. + */ export function upsertTags({ tagUpsertDto }: { tagUpsertDto: TagUpsertDto; }, opts?: Oazapfts.RequestOpts) { @@ -3644,6 +4064,9 @@ export function upsertTags({ tagUpsertDto }: { body: tagUpsertDto }))); } +/** + * This endpoint requires the `tag.asset` permission. + */ export function bulkTagAssets({ tagBulkAssetsDto }: { tagBulkAssetsDto: TagBulkAssetsDto; }, opts?: Oazapfts.RequestOpts) { @@ -3656,6 +4079,9 @@ export function bulkTagAssets({ tagBulkAssetsDto }: { body: tagBulkAssetsDto }))); } +/** + * This endpoint requires the `tag.delete` permission. + */ export function deleteTag({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3664,6 +4090,9 @@ export function deleteTag({ id }: { method: "DELETE" })); } +/** + * This endpoint requires the `tag.read` permission. + */ export function getTagById({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3674,6 +4103,9 @@ export function getTagById({ id }: { ...opts })); } +/** + * This endpoint requires the `tag.update` permission. + */ export function updateTag({ id, tagUpdateDto }: { id: string; tagUpdateDto: TagUpdateDto; @@ -3687,6 +4119,9 @@ export function updateTag({ id, tagUpdateDto }: { body: tagUpdateDto }))); } +/** + * This endpoint requires the `tag.asset` permission. + */ export function untagAssets({ id, bulkIdsDto }: { id: string; bulkIdsDto: BulkIdsDto; @@ -3700,6 +4135,9 @@ export function untagAssets({ id, bulkIdsDto }: { body: bulkIdsDto }))); } +/** + * This endpoint requires the `tag.asset` permission. + */ export function tagAssets({ id, bulkIdsDto }: { id: string; bulkIdsDto: BulkIdsDto; @@ -3713,6 +4151,9 @@ export function tagAssets({ id, bulkIdsDto }: { body: bulkIdsDto }))); } +/** + * This endpoint requires the `asset.read` permission. + */ export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, personId, slug, tagId, timeBucket, userId, visibility, withPartners, withStacked }: { albumId?: string; isFavorite?: boolean; @@ -3749,6 +4190,9 @@ export function getTimeBucket({ albumId, isFavorite, isTrashed, key, order, pers ...opts })); } +/** + * This endpoint requires the `asset.read` permission. + */ export function getTimeBuckets({ albumId, isFavorite, isTrashed, key, order, personId, slug, tagId, userId, visibility, withPartners, withStacked }: { albumId?: string; isFavorite?: boolean; @@ -3783,6 +4227,9 @@ export function getTimeBuckets({ albumId, isFavorite, isTrashed, key, order, per ...opts })); } +/** + * This endpoint requires the `asset.delete` permission. + */ export function emptyTrash(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3792,6 +4239,9 @@ export function emptyTrash(opts?: Oazapfts.RequestOpts) { method: "POST" })); } +/** + * This endpoint requires the `asset.delete` permission. + */ export function restoreTrash(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3801,6 +4251,9 @@ export function restoreTrash(opts?: Oazapfts.RequestOpts) { method: "POST" })); } +/** + * This endpoint requires the `asset.delete` permission. + */ export function restoreAssets({ bulkIdsDto }: { bulkIdsDto: BulkIdsDto; }, opts?: Oazapfts.RequestOpts) { @@ -3813,6 +4266,9 @@ export function restoreAssets({ bulkIdsDto }: { body: bulkIdsDto }))); } +/** + * This endpoint requires the `user.read` permission. + */ export function searchUsers(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3821,6 +4277,9 @@ export function searchUsers(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `user.read` permission. + */ export function getMyUser(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3829,6 +4288,9 @@ export function getMyUser(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `user.update` permission. + */ export function updateMyUser({ userUpdateMeDto }: { userUpdateMeDto: UserUpdateMeDto; }, opts?: Oazapfts.RequestOpts) { @@ -3841,12 +4303,18 @@ export function updateMyUser({ userUpdateMeDto }: { body: userUpdateMeDto }))); } +/** + * This endpoint requires the `userLicense.delete` permission. + */ export function deleteUserLicense(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchText("/users/me/license", { ...opts, method: "DELETE" })); } +/** + * This endpoint requires the `userLicense.read` permission. + */ export function getUserLicense(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3855,6 +4323,9 @@ export function getUserLicense(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `userLicense.update` permission. + */ export function setUserLicense({ licenseKeyDto }: { licenseKeyDto: LicenseKeyDto; }, opts?: Oazapfts.RequestOpts) { @@ -3867,12 +4338,18 @@ export function setUserLicense({ licenseKeyDto }: { body: licenseKeyDto }))); } +/** + * This endpoint requires the `userOnboarding.delete` permission. + */ export function deleteUserOnboarding(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchText("/users/me/onboarding", { ...opts, method: "DELETE" })); } +/** + * This endpoint requires the `userOnboarding.read` permission. + */ export function getUserOnboarding(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3881,6 +4358,9 @@ export function getUserOnboarding(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `userOnboarding.update` permission. + */ export function setUserOnboarding({ onboardingDto }: { onboardingDto: OnboardingDto; }, opts?: Oazapfts.RequestOpts) { @@ -3893,6 +4373,9 @@ export function setUserOnboarding({ onboardingDto }: { body: onboardingDto }))); } +/** + * This endpoint requires the `userPreference.read` permission. + */ export function getMyPreferences(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; @@ -3901,6 +4384,9 @@ export function getMyPreferences(opts?: Oazapfts.RequestOpts) { ...opts })); } +/** + * This endpoint requires the `userPreference.update` permission. + */ export function updateMyPreferences({ userPreferencesUpdateDto }: { userPreferencesUpdateDto: UserPreferencesUpdateDto; }, opts?: Oazapfts.RequestOpts) { @@ -3913,12 +4399,18 @@ export function updateMyPreferences({ userPreferencesUpdateDto }: { body: userPreferencesUpdateDto }))); } +/** + * This endpoint requires the `userProfileImage.delete` permission. + */ export function deleteProfileImage(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchText("/users/profile-image", { ...opts, method: "DELETE" })); } +/** + * This endpoint requires the `userProfileImage.update` permission. + */ export function createProfileImage({ createProfileImageDto }: { createProfileImageDto: CreateProfileImageDto; }, opts?: Oazapfts.RequestOpts) { @@ -3931,6 +4423,9 @@ export function createProfileImage({ createProfileImageDto }: { body: createProfileImageDto }))); } +/** + * This endpoint requires the `user.read` permission. + */ export function getUser({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { @@ -3941,6 +4436,9 @@ export function getUser({ id }: { ...opts })); } +/** + * This endpoint requires the `userProfileImage.read` permission. + */ export function getProfileImage({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { diff --git a/server/src/enum.ts b/server/src/enum.ts index 666b9fc50..93d271f19 100644 --- a/server/src/enum.ts +++ b/server/src/enum.ts @@ -413,6 +413,11 @@ export enum LogLevel { Fatal = 'fatal', } +export enum ApiCustomExtension { + Permission = 'x-immich-permission', + AdminOnly = 'x-immich-admin-only', +} + export enum MetadataKey { AuthRoute = 'auth_route', AdminRoute = 'admin_route', diff --git a/server/src/middleware/auth.guard.ts b/server/src/middleware/auth.guard.ts index 38ff1c373..80d7a3743 100644 --- a/server/src/middleware/auth.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -10,7 +10,7 @@ import { Reflector } from '@nestjs/core'; import { ApiBearerAuth, ApiCookieAuth, ApiExtension, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger'; import { Request } from 'express'; import { AuthDto } from 'src/dtos/auth.dto'; -import { ImmichQuery, MetadataKey, Permission } from 'src/enum'; +import { ApiCustomExtension, ImmichQuery, MetadataKey, Permission } from 'src/enum'; import { LoggingRepository } from 'src/repositories/logging.repository'; import { AuthService, LoginDetails } from 'src/services/auth.service'; import { UAParser } from 'ua-parser-js'; @@ -19,16 +19,20 @@ type AdminRoute = { admin?: true }; type SharedLinkRoute = { sharedLink?: true }; type AuthenticatedOptions = { permission?: Permission } & (AdminRoute | SharedLinkRoute); -export const Authenticated = (options?: AuthenticatedOptions): MethodDecorator => { +export const Authenticated = (options: AuthenticatedOptions = {}): MethodDecorator => { const decorators: MethodDecorator[] = [ ApiBearerAuth(), ApiCookieAuth(), ApiSecurity(MetadataKey.ApiKeySecurity), - SetMetadata(MetadataKey.AuthRoute, options || {}), + SetMetadata(MetadataKey.AuthRoute, options), ]; + if ((options as AdminRoute).admin) { + decorators.push(ApiExtension(ApiCustomExtension.AdminOnly, true)); + } + if (options?.permission) { - decorators.push(ApiExtension('x-immich-permission', options.permission)); + decorators.push(ApiExtension(ApiCustomExtension.Permission, options.permission ?? Permission.All)); } if ((options as SharedLinkRoute)?.sharedLink) { diff --git a/server/src/utils/misc.ts b/server/src/utils/misc.ts index 3acb72b66..a32632b52 100644 --- a/server/src/utils/misc.ts +++ b/server/src/utils/misc.ts @@ -6,7 +6,11 @@ import { SwaggerDocumentOptions, SwaggerModule, } from '@nestjs/swagger'; -import { ReferenceObject, SchemaObject } from '@nestjs/swagger/dist/interfaces/open-api-spec.interface'; +import { + OperationObject, + ReferenceObject, + SchemaObject, +} from '@nestjs/swagger/dist/interfaces/open-api-spec.interface'; import _ from 'lodash'; import { writeFileSync } from 'node:fs'; import path from 'node:path'; @@ -15,7 +19,7 @@ import parse from 'picomatch/lib/parse'; import { SystemConfig } from 'src/config'; import { CLIP_MODEL_INFO, serverVersion } from 'src/constants'; import { extraSyncModels } from 'src/dtos/sync.dto'; -import { ImmichCookie, ImmichHeader, MetadataKey } from 'src/enum'; +import { ApiCustomExtension, ImmichCookie, ImmichHeader, MetadataKey } from 'src/enum'; import { LoggingRepository } from 'src/repositories/logging.repository'; export class ImmichStartupError extends Error {} @@ -198,7 +202,12 @@ const patchOpenAPI = (document: OpenAPIObject) => { trace: path.trace, }; - for (const operation of Object.values(operations)) { + for (const operation of Object.values(operations) as Array< + OperationObject & { + [ApiCustomExtension.AdminOnly]?: boolean; + [ApiCustomExtension.Permission]?: string; + } + >) { if (!operation) { continue; } @@ -211,12 +220,21 @@ const patchOpenAPI = (document: OpenAPIObject) => { // console.log(`${routeToErrorMessage(operation.operationId).padEnd(40)} (${operation.operationId})`); } - if (operation.description === '') { - delete operation.description; - } + const adminOnly = operation[ApiCustomExtension.AdminOnly] ?? false; + const permission = operation[ApiCustomExtension.Permission]; + if (permission) { + let description = (operation.description || '').trim(); + if (description && !description.endsWith('.')) { + description += '. '; + } - if (operation.parameters) { - operation.parameters = _.orderBy(operation.parameters, 'name'); + operation.description = + description + + `This endpoint ${adminOnly ? 'is an admin-only route, and ' : ''}requires the \`${permission}\` permission.`; + + if (operation.parameters) { + operation.parameters = _.orderBy(operation.parameters, 'name'); + } } } }