Files
mCaptcha/src/db_sqlx_postgres/lib.rs.html
2022-05-27 13:55:17 +00:00

1888 lines
106 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Source of the Rust file `db/db-sqlx-postgres/src/lib.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>lib.rs - source</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Semibold.ttf.woff2"><link rel="stylesheet" type="text/css" href="../../normalize.css"><link rel="stylesheet" type="text/css" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../ayu.css" disabled><link rel="stylesheet" type="text/css" href="../../dark.css" disabled><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><script id="default-settings" ></script><script src="../../storage.js"></script><script src="../../crates.js"></script><script defer src="../../main.js"></script><script defer src="../../source-script.js"></script><script defer src="../../source-files.js"></script>
<noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="alternate icon" type="image/png" href="../../favicon-16x16.png"><link rel="alternate icon" type="image/png" href="../../favicon-32x32.png"><link rel="icon" type="image/svg+xml" href="../../favicon.svg"></head><body class="rustdoc source"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="mobile-topbar"><button class="sidebar-menu-toggle">&#9776;</button><a class="sidebar-logo" href="../../db_sqlx_postgres/index.html"><div class="logo-container"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></div>
</a><h2 class="location"></h2>
</nav>
<nav class="sidebar"><a class="sidebar-logo" href="../../db_sqlx_postgres/index.html"><div class="logo-container"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></div>
</a></nav><main><div class="width-limiter"><div class="sub-container"><a class="sub-logo-container" href="../../db_sqlx_postgres/index.html"><img class="rust-logo" src="../../rust-logo.svg" alt="logo"></a><nav class="sub"><div class="theme-picker hidden"><button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"><img width="22" height="22" alt="Pick another theme!" src="../../brush.svg"></button><div id="theme-choices" role="menu"></div></div><form class="search-form"><div class="search-container"><span></span><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"><button type="button" id="help-button" title="help">?</button><a id="settings-menu" href="../../settings.html" title="settings"><img width="22" height="22" alt="Change settings" src="../../wheel.svg"></a></div></form></nav></div><section id="main-content" class="content"><div class="example-wrap"><pre class="line-numbers"><span id="1">1</span>
<span id="2">2</span>
<span id="3">3</span>
<span id="4">4</span>
<span id="5">5</span>
<span id="6">6</span>
<span id="7">7</span>
<span id="8">8</span>
<span id="9">9</span>
<span id="10">10</span>
<span id="11">11</span>
<span id="12">12</span>
<span id="13">13</span>
<span id="14">14</span>
<span id="15">15</span>
<span id="16">16</span>
<span id="17">17</span>
<span id="18">18</span>
<span id="19">19</span>
<span id="20">20</span>
<span id="21">21</span>
<span id="22">22</span>
<span id="23">23</span>
<span id="24">24</span>
<span id="25">25</span>
<span id="26">26</span>
<span id="27">27</span>
<span id="28">28</span>
<span id="29">29</span>
<span id="30">30</span>
<span id="31">31</span>
<span id="32">32</span>
<span id="33">33</span>
<span id="34">34</span>
<span id="35">35</span>
<span id="36">36</span>
<span id="37">37</span>
<span id="38">38</span>
<span id="39">39</span>
<span id="40">40</span>
<span id="41">41</span>
<span id="42">42</span>
<span id="43">43</span>
<span id="44">44</span>
<span id="45">45</span>
<span id="46">46</span>
<span id="47">47</span>
<span id="48">48</span>
<span id="49">49</span>
<span id="50">50</span>
<span id="51">51</span>
<span id="52">52</span>
<span id="53">53</span>
<span id="54">54</span>
<span id="55">55</span>
<span id="56">56</span>
<span id="57">57</span>
<span id="58">58</span>
<span id="59">59</span>
<span id="60">60</span>
<span id="61">61</span>
<span id="62">62</span>
<span id="63">63</span>
<span id="64">64</span>
<span id="65">65</span>
<span id="66">66</span>
<span id="67">67</span>
<span id="68">68</span>
<span id="69">69</span>
<span id="70">70</span>
<span id="71">71</span>
<span id="72">72</span>
<span id="73">73</span>
<span id="74">74</span>
<span id="75">75</span>
<span id="76">76</span>
<span id="77">77</span>
<span id="78">78</span>
<span id="79">79</span>
<span id="80">80</span>
<span id="81">81</span>
<span id="82">82</span>
<span id="83">83</span>
<span id="84">84</span>
<span id="85">85</span>
<span id="86">86</span>
<span id="87">87</span>
<span id="88">88</span>
<span id="89">89</span>
<span id="90">90</span>
<span id="91">91</span>
<span id="92">92</span>
<span id="93">93</span>
<span id="94">94</span>
<span id="95">95</span>
<span id="96">96</span>
<span id="97">97</span>
<span id="98">98</span>
<span id="99">99</span>
<span id="100">100</span>
<span id="101">101</span>
<span id="102">102</span>
<span id="103">103</span>
<span id="104">104</span>
<span id="105">105</span>
<span id="106">106</span>
<span id="107">107</span>
<span id="108">108</span>
<span id="109">109</span>
<span id="110">110</span>
<span id="111">111</span>
<span id="112">112</span>
<span id="113">113</span>
<span id="114">114</span>
<span id="115">115</span>
<span id="116">116</span>
<span id="117">117</span>
<span id="118">118</span>
<span id="119">119</span>
<span id="120">120</span>
<span id="121">121</span>
<span id="122">122</span>
<span id="123">123</span>
<span id="124">124</span>
<span id="125">125</span>
<span id="126">126</span>
<span id="127">127</span>
<span id="128">128</span>
<span id="129">129</span>
<span id="130">130</span>
<span id="131">131</span>
<span id="132">132</span>
<span id="133">133</span>
<span id="134">134</span>
<span id="135">135</span>
<span id="136">136</span>
<span id="137">137</span>
<span id="138">138</span>
<span id="139">139</span>
<span id="140">140</span>
<span id="141">141</span>
<span id="142">142</span>
<span id="143">143</span>
<span id="144">144</span>
<span id="145">145</span>
<span id="146">146</span>
<span id="147">147</span>
<span id="148">148</span>
<span id="149">149</span>
<span id="150">150</span>
<span id="151">151</span>
<span id="152">152</span>
<span id="153">153</span>
<span id="154">154</span>
<span id="155">155</span>
<span id="156">156</span>
<span id="157">157</span>
<span id="158">158</span>
<span id="159">159</span>
<span id="160">160</span>
<span id="161">161</span>
<span id="162">162</span>
<span id="163">163</span>
<span id="164">164</span>
<span id="165">165</span>
<span id="166">166</span>
<span id="167">167</span>
<span id="168">168</span>
<span id="169">169</span>
<span id="170">170</span>
<span id="171">171</span>
<span id="172">172</span>
<span id="173">173</span>
<span id="174">174</span>
<span id="175">175</span>
<span id="176">176</span>
<span id="177">177</span>
<span id="178">178</span>
<span id="179">179</span>
<span id="180">180</span>
<span id="181">181</span>
<span id="182">182</span>
<span id="183">183</span>
<span id="184">184</span>
<span id="185">185</span>
<span id="186">186</span>
<span id="187">187</span>
<span id="188">188</span>
<span id="189">189</span>
<span id="190">190</span>
<span id="191">191</span>
<span id="192">192</span>
<span id="193">193</span>
<span id="194">194</span>
<span id="195">195</span>
<span id="196">196</span>
<span id="197">197</span>
<span id="198">198</span>
<span id="199">199</span>
<span id="200">200</span>
<span id="201">201</span>
<span id="202">202</span>
<span id="203">203</span>
<span id="204">204</span>
<span id="205">205</span>
<span id="206">206</span>
<span id="207">207</span>
<span id="208">208</span>
<span id="209">209</span>
<span id="210">210</span>
<span id="211">211</span>
<span id="212">212</span>
<span id="213">213</span>
<span id="214">214</span>
<span id="215">215</span>
<span id="216">216</span>
<span id="217">217</span>
<span id="218">218</span>
<span id="219">219</span>
<span id="220">220</span>
<span id="221">221</span>
<span id="222">222</span>
<span id="223">223</span>
<span id="224">224</span>
<span id="225">225</span>
<span id="226">226</span>
<span id="227">227</span>
<span id="228">228</span>
<span id="229">229</span>
<span id="230">230</span>
<span id="231">231</span>
<span id="232">232</span>
<span id="233">233</span>
<span id="234">234</span>
<span id="235">235</span>
<span id="236">236</span>
<span id="237">237</span>
<span id="238">238</span>
<span id="239">239</span>
<span id="240">240</span>
<span id="241">241</span>
<span id="242">242</span>
<span id="243">243</span>
<span id="244">244</span>
<span id="245">245</span>
<span id="246">246</span>
<span id="247">247</span>
<span id="248">248</span>
<span id="249">249</span>
<span id="250">250</span>
<span id="251">251</span>
<span id="252">252</span>
<span id="253">253</span>
<span id="254">254</span>
<span id="255">255</span>
<span id="256">256</span>
<span id="257">257</span>
<span id="258">258</span>
<span id="259">259</span>
<span id="260">260</span>
<span id="261">261</span>
<span id="262">262</span>
<span id="263">263</span>
<span id="264">264</span>
<span id="265">265</span>
<span id="266">266</span>
<span id="267">267</span>
<span id="268">268</span>
<span id="269">269</span>
<span id="270">270</span>
<span id="271">271</span>
<span id="272">272</span>
<span id="273">273</span>
<span id="274">274</span>
<span id="275">275</span>
<span id="276">276</span>
<span id="277">277</span>
<span id="278">278</span>
<span id="279">279</span>
<span id="280">280</span>
<span id="281">281</span>
<span id="282">282</span>
<span id="283">283</span>
<span id="284">284</span>
<span id="285">285</span>
<span id="286">286</span>
<span id="287">287</span>
<span id="288">288</span>
<span id="289">289</span>
<span id="290">290</span>
<span id="291">291</span>
<span id="292">292</span>
<span id="293">293</span>
<span id="294">294</span>
<span id="295">295</span>
<span id="296">296</span>
<span id="297">297</span>
<span id="298">298</span>
<span id="299">299</span>
<span id="300">300</span>
<span id="301">301</span>
<span id="302">302</span>
<span id="303">303</span>
<span id="304">304</span>
<span id="305">305</span>
<span id="306">306</span>
<span id="307">307</span>
<span id="308">308</span>
<span id="309">309</span>
<span id="310">310</span>
<span id="311">311</span>
<span id="312">312</span>
<span id="313">313</span>
<span id="314">314</span>
<span id="315">315</span>
<span id="316">316</span>
<span id="317">317</span>
<span id="318">318</span>
<span id="319">319</span>
<span id="320">320</span>
<span id="321">321</span>
<span id="322">322</span>
<span id="323">323</span>
<span id="324">324</span>
<span id="325">325</span>
<span id="326">326</span>
<span id="327">327</span>
<span id="328">328</span>
<span id="329">329</span>
<span id="330">330</span>
<span id="331">331</span>
<span id="332">332</span>
<span id="333">333</span>
<span id="334">334</span>
<span id="335">335</span>
<span id="336">336</span>
<span id="337">337</span>
<span id="338">338</span>
<span id="339">339</span>
<span id="340">340</span>
<span id="341">341</span>
<span id="342">342</span>
<span id="343">343</span>
<span id="344">344</span>
<span id="345">345</span>
<span id="346">346</span>
<span id="347">347</span>
<span id="348">348</span>
<span id="349">349</span>
<span id="350">350</span>
<span id="351">351</span>
<span id="352">352</span>
<span id="353">353</span>
<span id="354">354</span>
<span id="355">355</span>
<span id="356">356</span>
<span id="357">357</span>
<span id="358">358</span>
<span id="359">359</span>
<span id="360">360</span>
<span id="361">361</span>
<span id="362">362</span>
<span id="363">363</span>
<span id="364">364</span>
<span id="365">365</span>
<span id="366">366</span>
<span id="367">367</span>
<span id="368">368</span>
<span id="369">369</span>
<span id="370">370</span>
<span id="371">371</span>
<span id="372">372</span>
<span id="373">373</span>
<span id="374">374</span>
<span id="375">375</span>
<span id="376">376</span>
<span id="377">377</span>
<span id="378">378</span>
<span id="379">379</span>
<span id="380">380</span>
<span id="381">381</span>
<span id="382">382</span>
<span id="383">383</span>
<span id="384">384</span>
<span id="385">385</span>
<span id="386">386</span>
<span id="387">387</span>
<span id="388">388</span>
<span id="389">389</span>
<span id="390">390</span>
<span id="391">391</span>
<span id="392">392</span>
<span id="393">393</span>
<span id="394">394</span>
<span id="395">395</span>
<span id="396">396</span>
<span id="397">397</span>
<span id="398">398</span>
<span id="399">399</span>
<span id="400">400</span>
<span id="401">401</span>
<span id="402">402</span>
<span id="403">403</span>
<span id="404">404</span>
<span id="405">405</span>
<span id="406">406</span>
<span id="407">407</span>
<span id="408">408</span>
<span id="409">409</span>
<span id="410">410</span>
<span id="411">411</span>
<span id="412">412</span>
<span id="413">413</span>
<span id="414">414</span>
<span id="415">415</span>
<span id="416">416</span>
<span id="417">417</span>
<span id="418">418</span>
<span id="419">419</span>
<span id="420">420</span>
<span id="421">421</span>
<span id="422">422</span>
<span id="423">423</span>
<span id="424">424</span>
<span id="425">425</span>
<span id="426">426</span>
<span id="427">427</span>
<span id="428">428</span>
<span id="429">429</span>
<span id="430">430</span>
<span id="431">431</span>
<span id="432">432</span>
<span id="433">433</span>
<span id="434">434</span>
<span id="435">435</span>
<span id="436">436</span>
<span id="437">437</span>
<span id="438">438</span>
<span id="439">439</span>
<span id="440">440</span>
<span id="441">441</span>
<span id="442">442</span>
<span id="443">443</span>
<span id="444">444</span>
<span id="445">445</span>
<span id="446">446</span>
<span id="447">447</span>
<span id="448">448</span>
<span id="449">449</span>
<span id="450">450</span>
<span id="451">451</span>
<span id="452">452</span>
<span id="453">453</span>
<span id="454">454</span>
<span id="455">455</span>
<span id="456">456</span>
<span id="457">457</span>
<span id="458">458</span>
<span id="459">459</span>
<span id="460">460</span>
<span id="461">461</span>
<span id="462">462</span>
<span id="463">463</span>
<span id="464">464</span>
<span id="465">465</span>
<span id="466">466</span>
<span id="467">467</span>
<span id="468">468</span>
<span id="469">469</span>
<span id="470">470</span>
<span id="471">471</span>
<span id="472">472</span>
<span id="473">473</span>
<span id="474">474</span>
<span id="475">475</span>
<span id="476">476</span>
<span id="477">477</span>
<span id="478">478</span>
<span id="479">479</span>
<span id="480">480</span>
<span id="481">481</span>
<span id="482">482</span>
<span id="483">483</span>
<span id="484">484</span>
<span id="485">485</span>
<span id="486">486</span>
<span id="487">487</span>
<span id="488">488</span>
<span id="489">489</span>
<span id="490">490</span>
<span id="491">491</span>
<span id="492">492</span>
<span id="493">493</span>
<span id="494">494</span>
<span id="495">495</span>
<span id="496">496</span>
<span id="497">497</span>
<span id="498">498</span>
<span id="499">499</span>
<span id="500">500</span>
<span id="501">501</span>
<span id="502">502</span>
<span id="503">503</span>
<span id="504">504</span>
<span id="505">505</span>
<span id="506">506</span>
<span id="507">507</span>
<span id="508">508</span>
<span id="509">509</span>
<span id="510">510</span>
<span id="511">511</span>
<span id="512">512</span>
<span id="513">513</span>
<span id="514">514</span>
<span id="515">515</span>
<span id="516">516</span>
<span id="517">517</span>
<span id="518">518</span>
<span id="519">519</span>
<span id="520">520</span>
<span id="521">521</span>
<span id="522">522</span>
<span id="523">523</span>
<span id="524">524</span>
<span id="525">525</span>
<span id="526">526</span>
<span id="527">527</span>
<span id="528">528</span>
<span id="529">529</span>
<span id="530">530</span>
<span id="531">531</span>
<span id="532">532</span>
<span id="533">533</span>
<span id="534">534</span>
<span id="535">535</span>
<span id="536">536</span>
<span id="537">537</span>
<span id="538">538</span>
<span id="539">539</span>
<span id="540">540</span>
<span id="541">541</span>
<span id="542">542</span>
<span id="543">543</span>
<span id="544">544</span>
<span id="545">545</span>
<span id="546">546</span>
<span id="547">547</span>
<span id="548">548</span>
<span id="549">549</span>
<span id="550">550</span>
<span id="551">551</span>
<span id="552">552</span>
<span id="553">553</span>
<span id="554">554</span>
<span id="555">555</span>
<span id="556">556</span>
<span id="557">557</span>
<span id="558">558</span>
<span id="559">559</span>
<span id="560">560</span>
<span id="561">561</span>
<span id="562">562</span>
<span id="563">563</span>
<span id="564">564</span>
<span id="565">565</span>
<span id="566">566</span>
<span id="567">567</span>
<span id="568">568</span>
<span id="569">569</span>
<span id="570">570</span>
<span id="571">571</span>
<span id="572">572</span>
<span id="573">573</span>
<span id="574">574</span>
<span id="575">575</span>
<span id="576">576</span>
<span id="577">577</span>
<span id="578">578</span>
<span id="579">579</span>
<span id="580">580</span>
<span id="581">581</span>
<span id="582">582</span>
<span id="583">583</span>
<span id="584">584</span>
<span id="585">585</span>
<span id="586">586</span>
<span id="587">587</span>
<span id="588">588</span>
<span id="589">589</span>
<span id="590">590</span>
<span id="591">591</span>
<span id="592">592</span>
<span id="593">593</span>
<span id="594">594</span>
<span id="595">595</span>
<span id="596">596</span>
<span id="597">597</span>
<span id="598">598</span>
<span id="599">599</span>
<span id="600">600</span>
<span id="601">601</span>
<span id="602">602</span>
<span id="603">603</span>
<span id="604">604</span>
<span id="605">605</span>
<span id="606">606</span>
<span id="607">607</span>
<span id="608">608</span>
<span id="609">609</span>
<span id="610">610</span>
<span id="611">611</span>
<span id="612">612</span>
<span id="613">613</span>
<span id="614">614</span>
<span id="615">615</span>
<span id="616">616</span>
<span id="617">617</span>
<span id="618">618</span>
<span id="619">619</span>
<span id="620">620</span>
<span id="621">621</span>
<span id="622">622</span>
<span id="623">623</span>
<span id="624">624</span>
<span id="625">625</span>
<span id="626">626</span>
<span id="627">627</span>
<span id="628">628</span>
<span id="629">629</span>
<span id="630">630</span>
<span id="631">631</span>
<span id="632">632</span>
<span id="633">633</span>
<span id="634">634</span>
<span id="635">635</span>
<span id="636">636</span>
<span id="637">637</span>
<span id="638">638</span>
<span id="639">639</span>
<span id="640">640</span>
<span id="641">641</span>
<span id="642">642</span>
<span id="643">643</span>
<span id="644">644</span>
<span id="645">645</span>
<span id="646">646</span>
<span id="647">647</span>
<span id="648">648</span>
<span id="649">649</span>
<span id="650">650</span>
<span id="651">651</span>
<span id="652">652</span>
<span id="653">653</span>
<span id="654">654</span>
<span id="655">655</span>
<span id="656">656</span>
<span id="657">657</span>
<span id="658">658</span>
<span id="659">659</span>
<span id="660">660</span>
<span id="661">661</span>
<span id="662">662</span>
<span id="663">663</span>
<span id="664">664</span>
<span id="665">665</span>
<span id="666">666</span>
<span id="667">667</span>
<span id="668">668</span>
<span id="669">669</span>
<span id="670">670</span>
<span id="671">671</span>
<span id="672">672</span>
<span id="673">673</span>
<span id="674">674</span>
<span id="675">675</span>
<span id="676">676</span>
<span id="677">677</span>
<span id="678">678</span>
<span id="679">679</span>
<span id="680">680</span>
<span id="681">681</span>
<span id="682">682</span>
<span id="683">683</span>
<span id="684">684</span>
<span id="685">685</span>
<span id="686">686</span>
<span id="687">687</span>
<span id="688">688</span>
<span id="689">689</span>
<span id="690">690</span>
<span id="691">691</span>
<span id="692">692</span>
<span id="693">693</span>
<span id="694">694</span>
<span id="695">695</span>
<span id="696">696</span>
<span id="697">697</span>
<span id="698">698</span>
<span id="699">699</span>
<span id="700">700</span>
<span id="701">701</span>
<span id="702">702</span>
<span id="703">703</span>
<span id="704">704</span>
<span id="705">705</span>
<span id="706">706</span>
<span id="707">707</span>
<span id="708">708</span>
<span id="709">709</span>
<span id="710">710</span>
<span id="711">711</span>
<span id="712">712</span>
<span id="713">713</span>
<span id="714">714</span>
<span id="715">715</span>
<span id="716">716</span>
<span id="717">717</span>
<span id="718">718</span>
<span id="719">719</span>
<span id="720">720</span>
<span id="721">721</span>
<span id="722">722</span>
<span id="723">723</span>
<span id="724">724</span>
<span id="725">725</span>
<span id="726">726</span>
<span id="727">727</span>
<span id="728">728</span>
<span id="729">729</span>
<span id="730">730</span>
<span id="731">731</span>
<span id="732">732</span>
<span id="733">733</span>
<span id="734">734</span>
<span id="735">735</span>
<span id="736">736</span>
<span id="737">737</span>
<span id="738">738</span>
<span id="739">739</span>
<span id="740">740</span>
<span id="741">741</span>
<span id="742">742</span>
<span id="743">743</span>
<span id="744">744</span>
<span id="745">745</span>
<span id="746">746</span>
<span id="747">747</span>
<span id="748">748</span>
<span id="749">749</span>
<span id="750">750</span>
<span id="751">751</span>
<span id="752">752</span>
<span id="753">753</span>
<span id="754">754</span>
<span id="755">755</span>
<span id="756">756</span>
<span id="757">757</span>
<span id="758">758</span>
<span id="759">759</span>
<span id="760">760</span>
<span id="761">761</span>
<span id="762">762</span>
<span id="763">763</span>
<span id="764">764</span>
<span id="765">765</span>
<span id="766">766</span>
<span id="767">767</span>
<span id="768">768</span>
<span id="769">769</span>
<span id="770">770</span>
<span id="771">771</span>
<span id="772">772</span>
<span id="773">773</span>
<span id="774">774</span>
<span id="775">775</span>
<span id="776">776</span>
<span id="777">777</span>
<span id="778">778</span>
<span id="779">779</span>
<span id="780">780</span>
<span id="781">781</span>
<span id="782">782</span>
<span id="783">783</span>
<span id="784">784</span>
<span id="785">785</span>
<span id="786">786</span>
<span id="787">787</span>
<span id="788">788</span>
<span id="789">789</span>
<span id="790">790</span>
<span id="791">791</span>
<span id="792">792</span>
<span id="793">793</span>
<span id="794">794</span>
<span id="795">795</span>
<span id="796">796</span>
<span id="797">797</span>
<span id="798">798</span>
<span id="799">799</span>
<span id="800">800</span>
<span id="801">801</span>
<span id="802">802</span>
<span id="803">803</span>
<span id="804">804</span>
<span id="805">805</span>
<span id="806">806</span>
<span id="807">807</span>
<span id="808">808</span>
<span id="809">809</span>
<span id="810">810</span>
<span id="811">811</span>
<span id="812">812</span>
<span id="813">813</span>
<span id="814">814</span>
<span id="815">815</span>
<span id="816">816</span>
<span id="817">817</span>
<span id="818">818</span>
<span id="819">819</span>
<span id="820">820</span>
<span id="821">821</span>
<span id="822">822</span>
<span id="823">823</span>
<span id="824">824</span>
<span id="825">825</span>
<span id="826">826</span>
<span id="827">827</span>
<span id="828">828</span>
<span id="829">829</span>
<span id="830">830</span>
<span id="831">831</span>
<span id="832">832</span>
<span id="833">833</span>
<span id="834">834</span>
<span id="835">835</span>
<span id="836">836</span>
<span id="837">837</span>
<span id="838">838</span>
<span id="839">839</span>
<span id="840">840</span>
<span id="841">841</span>
<span id="842">842</span>
<span id="843">843</span>
<span id="844">844</span>
<span id="845">845</span>
<span id="846">846</span>
<span id="847">847</span>
<span id="848">848</span>
<span id="849">849</span>
<span id="850">850</span>
<span id="851">851</span>
<span id="852">852</span>
<span id="853">853</span>
<span id="854">854</span>
<span id="855">855</span>
<span id="856">856</span>
<span id="857">857</span>
<span id="858">858</span>
<span id="859">859</span>
<span id="860">860</span>
<span id="861">861</span>
<span id="862">862</span>
<span id="863">863</span>
<span id="864">864</span>
<span id="865">865</span>
<span id="866">866</span>
<span id="867">867</span>
<span id="868">868</span>
<span id="869">869</span>
<span id="870">870</span>
<span id="871">871</span>
<span id="872">872</span>
<span id="873">873</span>
<span id="874">874</span>
<span id="875">875</span>
<span id="876">876</span>
<span id="877">877</span>
<span id="878">878</span>
<span id="879">879</span>
<span id="880">880</span>
<span id="881">881</span>
<span id="882">882</span>
<span id="883">883</span>
<span id="884">884</span>
<span id="885">885</span>
<span id="886">886</span>
<span id="887">887</span>
<span id="888">888</span>
<span id="889">889</span>
<span id="890">890</span>
<span id="891">891</span>
<span id="892">892</span>
<span id="893">893</span>
<span id="894">894</span>
<span id="895">895</span>
<span id="896">896</span>
<span id="897">897</span>
<span id="898">898</span>
<span id="899">899</span>
<span id="900">900</span>
<span id="901">901</span>
<span id="902">902</span>
<span id="903">903</span>
<span id="904">904</span>
<span id="905">905</span>
<span id="906">906</span>
<span id="907">907</span>
<span id="908">908</span>
<span id="909">909</span>
<span id="910">910</span>
<span id="911">911</span>
<span id="912">912</span>
<span id="913">913</span>
<span id="914">914</span>
<span id="915">915</span>
<span id="916">916</span>
<span id="917">917</span>
<span id="918">918</span>
<span id="919">919</span>
<span id="920">920</span>
<span id="921">921</span>
<span id="922">922</span>
<span id="923">923</span>
<span id="924">924</span>
<span id="925">925</span>
<span id="926">926</span>
<span id="927">927</span>
<span id="928">928</span>
<span id="929">929</span>
<span id="930">930</span>
<span id="931">931</span>
<span id="932">932</span>
<span id="933">933</span>
<span id="934">934</span>
<span id="935">935</span>
<span id="936">936</span>
<span id="937">937</span>
<span id="938">938</span>
<span id="939">939</span>
<span id="940">940</span>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see &lt;https://www.gnu.org/licenses/&gt;.
*/</span>
<span class="kw">use</span> <span class="ident">db_core::dev</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">sqlx::postgres::PgPoolOptions</span>;
<span class="kw">use</span> <span class="ident">sqlx::types::time::OffsetDateTime</span>;
<span class="kw">use</span> <span class="ident">sqlx::PgPool</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">errors</span>;
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Database</span> {
<span class="kw">pub</span> <span class="ident">pool</span>: <span class="ident">PgPool</span>,
}
<span class="doccomment">/// Use an existing database pool</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Conn</span>(<span class="kw">pub</span> <span class="ident">PgPool</span>);
<span class="doccomment">/// Connect to databse</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">ConnectionOptions</span> {
<span class="doccomment">/// fresh connection</span>
<span class="ident">Fresh</span>(<span class="ident">Fresh</span>),
<span class="doccomment">/// existing connection</span>
<span class="ident">Existing</span>(<span class="ident">Conn</span>),
}
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Fresh</span> {
<span class="kw">pub</span> <span class="ident">pool_options</span>: <span class="ident">PgPoolOptions</span>,
<span class="kw">pub</span> <span class="ident">url</span>: <span class="ident">String</span>,
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">dev</span> {
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident"><span class="kw">super</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident"><span class="kw">super</span>::Database</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">db_core::dev</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">prelude</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">sqlx::Error</span>;
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">prelude</span> {
<span class="kw">pub</span> <span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">db_core::prelude</span>::<span class="kw-2">*</span>;
}
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">impl</span> <span class="ident">Connect</span> <span class="kw">for</span> <span class="ident">ConnectionOptions</span> {
<span class="kw">type</span> <span class="ident">Pool</span> <span class="op">=</span> <span class="ident">Database</span>;
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">connect</span>(<span class="self">self</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident"><span class="self">Self</span>::Pool</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">pool</span> <span class="op">=</span> <span class="kw">match</span> <span class="self">self</span> {
<span class="ident"><span class="self">Self</span>::Fresh</span>(<span class="ident">fresh</span>) =&gt; <span class="ident">fresh</span>
.<span class="ident">pool_options</span>
.<span class="ident">connect</span>(<span class="kw-2">&amp;</span><span class="ident">fresh</span>.<span class="ident">url</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">DBError::DBError</span>(<span class="ident">Box::new</span>(<span class="ident">e</span>)))<span class="question-mark">?</span>,
<span class="ident"><span class="self">Self</span>::Existing</span>(<span class="ident">conn</span>) =&gt; <span class="ident">conn</span>.<span class="number">0</span>,
};
<span class="prelude-val">Ok</span>(<span class="ident">Database</span> { <span class="ident">pool</span> })
}
}
<span class="kw">use</span> <span class="ident">dev</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">impl</span> <span class="ident">Migrate</span> <span class="kw">for</span> <span class="ident">Database</span> {
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">migrate</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::migrate!</span>(<span class="string">&quot;./migrations/&quot;</span>)
.<span class="ident">run</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">DBError::DBError</span>(<span class="ident">Box::new</span>(<span class="ident">e</span>)))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
}
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">impl</span> <span class="ident">MCDatabase</span> <span class="kw">for</span> <span class="ident">Database</span> {
<span class="doccomment">/// ping DB</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">ping</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">bool</span> {
<span class="kw">use</span> <span class="ident">sqlx::Connection</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="kw-2">mut</span> <span class="ident">con</span>) <span class="op">=</span> <span class="self">self</span>.<span class="ident">pool</span>.<span class="ident">acquire</span>().<span class="kw">await</span> {
<span class="ident">con</span>.<span class="ident">ping</span>().<span class="kw">await</span>.<span class="ident">is_ok</span>()
} <span class="kw">else</span> {
<span class="bool-val">false</span>
}
}
<span class="doccomment">/// register a new user</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">register</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">p</span>: <span class="kw-2">&amp;</span><span class="ident">Register</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">email</span>) <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">email</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;insert into mcaptcha_users
(name , password, email, secret) values ($1, $2, $3, $4)&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">username</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">hash</span>,
<span class="kw-2">&amp;</span><span class="ident">email</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">secret</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
} <span class="kw">else</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_users
(name , password, secret) VALUES ($1, $2, $3)&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">username</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">hash</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">secret</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
};
<span class="ident">res</span>.<span class="ident">map_err</span>(<span class="ident">map_register_err</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// delete a user</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">delete_user</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(<span class="string">&quot;DELETE FROM mcaptcha_users WHERE name = ($1)&quot;</span>, <span class="ident">username</span>)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// check if username exists</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">username_exists</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">bool</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;SELECT EXISTS (SELECT 1 from mcaptcha_users WHERE name = $1)&quot;</span>,
<span class="ident">username</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">map_register_err</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">resp</span> <span class="op">=</span> <span class="bool-val">false</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">x</span>) <span class="op">=</span> <span class="ident">res</span>.<span class="ident">exists</span> {
<span class="ident">resp</span> <span class="op">=</span> <span class="ident">x</span>;
}
<span class="prelude-val">Ok</span>(<span class="ident">resp</span>)
}
<span class="doccomment">/// get user email</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_email</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">struct</span> <span class="ident">Email</span> {
<span class="ident">email</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>,
}
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Email</span>,
<span class="string">&quot;SELECT email FROM mcaptcha_users WHERE name = $1&quot;</span>,
<span class="ident">username</span>
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">res</span>.<span class="ident">email</span>)
}
<span class="doccomment">/// check if email exists</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">email_exists</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">email</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">bool</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;SELECT EXISTS (SELECT 1 from mcaptcha_users WHERE email = $1)&quot;</span>,
<span class="ident">email</span>
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">map_register_err</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">resp</span> <span class="op">=</span> <span class="bool-val">false</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">x</span>) <span class="op">=</span> <span class="ident">res</span>.<span class="ident">exists</span> {
<span class="ident">resp</span> <span class="op">=</span> <span class="ident">x</span>;
}
<span class="prelude-val">Ok</span>(<span class="ident">resp</span>)
}
<span class="doccomment">/// update a user&#39;s email</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_email</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">p</span>: <span class="kw-2">&amp;</span><span class="ident">UpdateEmail</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;UPDATE mcaptcha_users set email = $1
WHERE name = $2&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">new_email</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">username</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// get a user&#39;s password</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">l</span>: <span class="kw-2">&amp;</span><span class="ident">Login</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">NameHash</span><span class="op">&gt;</span> {
<span class="kw">struct</span> <span class="ident">Password</span> {
<span class="ident">name</span>: <span class="ident">String</span>,
<span class="ident">password</span>: <span class="ident">String</span>,
}
<span class="kw">let</span> <span class="ident">rec</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">l</span> {
<span class="ident">Login::Username</span>(<span class="ident">u</span>) =&gt; <span class="macro">sqlx::query_as!</span>(
<span class="ident">Password</span>,
<span class="string">r#&quot;SELECT name, password FROM mcaptcha_users WHERE name = ($1)&quot;#</span>,
<span class="ident">u</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>,
<span class="ident">Login::Email</span>(<span class="ident">e</span>) =&gt; <span class="macro">sqlx::query_as!</span>(
<span class="ident">Password</span>,
<span class="string">r#&quot;SELECT name, password FROM mcaptcha_users WHERE email = ($1)&quot;#</span>,
<span class="ident">e</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>,
};
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">NameHash</span> {
<span class="ident">hash</span>: <span class="ident">rec</span>.<span class="ident">password</span>,
<span class="ident">username</span>: <span class="ident">rec</span>.<span class="ident">name</span>,
};
<span class="prelude-val">Ok</span>(<span class="ident">res</span>)
}
<span class="doccomment">/// update user&#39;s password</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_password</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">p</span>: <span class="kw-2">&amp;</span><span class="ident">NameHash</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;UPDATE mcaptcha_users set password = $1
WHERE name = $2&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">hash</span>,
<span class="kw-2">&amp;</span><span class="ident">p</span>.<span class="ident">username</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// update username</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_username</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">current</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">new</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;UPDATE mcaptcha_users set name = $1
WHERE name = $2&quot;</span>,
<span class="ident">new</span>,
<span class="ident">current</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// get a user&#39;s secret</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_secret</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Secret</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">secret</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Secret</span>,
<span class="string">r#&quot;SELECT secret FROM mcaptcha_users WHERE name = ($1)&quot;#</span>,
<span class="ident">username</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">secret</span>)
}
<span class="doccomment">/// update a user&#39;s secret</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_secret</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">secret</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;UPDATE mcaptcha_users set secret = $1
WHERE name = $2&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">secret</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// create new captcha</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">create_captcha</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">p</span>: <span class="kw-2">&amp;</span><span class="ident">CreateCaptcha</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_config
(key, user_id, duration, name)
VALUES ($1, (SELECT ID FROM mcaptcha_users WHERE name = $2), $3, $4)&quot;</span>,
<span class="ident">p</span>.<span class="ident">key</span>,
<span class="ident">username</span>,
<span class="ident">p</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="ident">p</span>.<span class="ident">description</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// Get captcha config</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_captcha_config</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Captcha</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">captcha</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">InternaleCaptchaConfig</span>,
<span class="string">&quot;SELECT config_id, duration, name, key from mcaptcha_config WHERE
key = $1 AND
user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2) &quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">captcha</span>.<span class="ident">into</span>())
}
<span class="doccomment">/// Get all captchas belonging to user</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_all_user_captchas</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Captcha</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">res</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">InternaleCaptchaConfig</span>,
<span class="string">&quot;SELECT key, name, config_id, duration FROM mcaptcha_config WHERE
user_id = (SELECT ID FROM mcaptcha_users WHERE name = $1) &quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>,
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">captchas</span> <span class="op">=</span> <span class="ident">Vec::with_capacity</span>(<span class="ident">res</span>.<span class="ident">len</span>());
<span class="ident">res</span>.<span class="ident">drain</span>(<span class="number">0</span>..).<span class="ident">for_each</span>(<span class="op">|</span><span class="ident">r</span><span class="op">|</span> <span class="ident">captchas</span>.<span class="ident">push</span>(<span class="ident">r</span>.<span class="ident">into</span>()));
<span class="prelude-val">Ok</span>(<span class="ident">captchas</span>)
}
<span class="doccomment">/// update captcha metadata; doesn&#39;t change captcha key</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_captcha_metadata</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">p</span>: <span class="kw-2">&amp;</span><span class="ident">CreateCaptcha</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;UPDATE mcaptcha_config SET name = $1, duration = $2
WHERE user_id = (SELECT ID FROM mcaptcha_users WHERE name = $3)
AND key = $4&quot;</span>,
<span class="ident">p</span>.<span class="ident">description</span>,
<span class="ident">p</span>.<span class="ident">duration</span>,
<span class="ident">username</span>,
<span class="ident">p</span>.<span class="ident">key</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// update captcha key; doesn&#39;t change metadata</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_captcha_key</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">old_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">new_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;UPDATE mcaptcha_config SET key = $1
WHERE key = $2 AND user_id = (SELECT ID FROM mcaptcha_users WHERE name = $3)&quot;</span>,
<span class="ident">new_key</span>,
<span class="ident">old_key</span>,
<span class="ident">username</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// Add levels to captcha</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">add_captcha_levels</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">levels</span>: <span class="kw-2">&amp;</span>[<span class="ident">Level</span>],
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">use</span> <span class="ident">futures::future::try_join_all</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">futs</span> <span class="op">=</span> <span class="ident">Vec::with_capacity</span>(<span class="ident">levels</span>.<span class="ident">len</span>());
<span class="kw">for</span> <span class="ident">level</span> <span class="kw">in</span> <span class="ident">levels</span>.<span class="ident">iter</span>() {
<span class="kw">let</span> <span class="ident">difficulty_factor</span> <span class="op">=</span> <span class="ident">level</span>.<span class="ident">difficulty_factor</span> <span class="kw">as</span> <span class="ident">i32</span>;
<span class="kw">let</span> <span class="ident">visitor_threshold</span> <span class="op">=</span> <span class="ident">level</span>.<span class="ident">visitor_threshold</span> <span class="kw">as</span> <span class="ident">i32</span>;
<span class="kw">let</span> <span class="ident">fut</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_levels (
difficulty_factor,
visitor_threshold,
config_id) VALUES (
$1, $2, (
SELECT config_id FROM mcaptcha_config WHERE
key = ($3) AND user_id = (
SELECT ID FROM mcaptcha_users WHERE name = $4
)));&quot;</span>,
<span class="ident">difficulty_factor</span>,
<span class="ident">visitor_threshold</span>,
<span class="kw-2">&amp;</span><span class="ident">captcha_key</span>,
<span class="ident">username</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>);
<span class="ident">futs</span>.<span class="ident">push</span>(<span class="ident">fut</span>);
}
<span class="ident">try_join_all</span>(<span class="ident">futs</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// check if captcha exists</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">captcha_exists</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="kw-2">&amp;</span><span class="ident">str</span><span class="op">&gt;</span>,
<span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">bool</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">exists</span> <span class="op">=</span> <span class="bool-val">false</span>;
<span class="kw">match</span> <span class="ident">username</span> {
<span class="prelude-val">Some</span>(<span class="ident">username</span>) =&gt; {
<span class="kw">let</span> <span class="ident">x</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;SELECT EXISTS (
SELECT 1 from mcaptcha_config WHERE key = $1
AND user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2)
)&quot;</span>,
<span class="ident">captcha_key</span>,
<span class="ident">username</span>
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">map_register_err</span>)<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">x</span>) <span class="op">=</span> <span class="ident">x</span>.<span class="ident">exists</span> {
<span class="ident">exists</span> <span class="op">=</span> <span class="ident">x</span>;
};
}
<span class="prelude-val">None</span> =&gt; {
<span class="kw">let</span> <span class="ident">x</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;SELECT EXISTS (SELECT 1 from mcaptcha_config WHERE key = $1)&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">captcha_key</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">map_register_err</span>)<span class="question-mark">?</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">x</span>) <span class="op">=</span> <span class="ident">x</span>.<span class="ident">exists</span> {
<span class="ident">exists</span> <span class="op">=</span> <span class="ident">x</span>;
};
}
};
<span class="prelude-val">Ok</span>(<span class="ident">exists</span>)
}
<span class="doccomment">/// Delete all levels of a captcha</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">delete_captcha_levels</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;DELETE FROM mcaptcha_levels
WHERE config_id = (
SELECT config_id FROM mcaptcha_config where key = ($1)
AND user_id = (
SELECT ID from mcaptcha_users WHERE name = $2
)
)&quot;</span>,
<span class="ident">captcha_key</span>,
<span class="ident">username</span>
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// Delete captcha</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">delete_captcha</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;DELETE FROM mcaptcha_config WHERE key = ($1)
AND
user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2)&quot;</span>,
<span class="ident">captcha_key</span>,
<span class="ident">username</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// Get captcha levels</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_captcha_levels</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="kw-2">&amp;</span><span class="ident">str</span><span class="op">&gt;</span>,
<span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Level</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">struct</span> <span class="ident">I32Levels</span> {
<span class="ident">difficulty_factor</span>: <span class="ident">i32</span>,
<span class="ident">visitor_threshold</span>: <span class="ident">i32</span>,
}
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="kw">match</span> <span class="ident">username</span> {
<span class="prelude-val">None</span> =&gt; <span class="macro">sqlx::query_as!</span>(
<span class="ident">I32Levels</span>,
<span class="string">&quot;SELECT difficulty_factor, visitor_threshold FROM mcaptcha_levels WHERE
config_id = (
SELECT config_id FROM mcaptcha_config WHERE key = ($1)
) ORDER BY difficulty_factor ASC;&quot;</span>,
<span class="ident">captcha_key</span>,
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>,
<span class="prelude-val">Some</span>(<span class="ident">username</span>) =&gt; <span class="macro">sqlx::query_as!</span>(
<span class="ident">I32Levels</span>,
<span class="string">&quot;SELECT difficulty_factor, visitor_threshold FROM mcaptcha_levels WHERE
config_id = (
SELECT config_id FROM mcaptcha_config WHERE key = ($1)
AND user_id = (SELECT ID from mcaptcha_users WHERE name = $2)
)
ORDER BY difficulty_factor ASC;&quot;</span>,
<span class="ident">captcha_key</span>,
<span class="ident">username</span>
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>,
};
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">new_levels</span> <span class="op">=</span> <span class="ident">Vec::with_capacity</span>(<span class="ident">levels</span>.<span class="ident">len</span>());
<span class="kw">for</span> <span class="ident">l</span> <span class="kw">in</span> <span class="ident">levels</span>.<span class="ident">iter</span>() {
<span class="ident">new_levels</span>.<span class="ident">push</span>(<span class="ident">Level</span> {
<span class="ident">difficulty_factor</span>: <span class="ident">l</span>.<span class="ident">difficulty_factor</span> <span class="kw">as</span> <span class="ident">u32</span>,
<span class="ident">visitor_threshold</span>: <span class="ident">l</span>.<span class="ident">visitor_threshold</span> <span class="kw">as</span> <span class="ident">u32</span>,
});
}
<span class="prelude-val">Ok</span>(<span class="ident">new_levels</span>)
}
<span class="doccomment">/// Get captcha&#39;s cooldown period</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_captcha_cooldown</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">i32</span><span class="op">&gt;</span> {
<span class="kw">struct</span> <span class="ident">DurationResp</span> {
<span class="ident">duration</span>: <span class="ident">i32</span>,
}
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">DurationResp</span>,
<span class="string">&quot;SELECT duration FROM mcaptcha_config
WHERE key = $1&quot;</span>,
<span class="ident">captcha_key</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">resp</span>.<span class="ident">duration</span>)
}
<span class="doccomment">/// Add traffic configuration</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">add_traffic_pattern</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">pattern</span>: <span class="kw-2">&amp;</span><span class="ident">TrafficPattern</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_sitekey_user_provided_avg_traffic (
config_id,
avg_traffic,
peak_sustainable_traffic,
broke_my_site_traffic
) VALUES (
(SELECT config_id FROM mcaptcha_config WHERE key = ($1)
AND user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2)
), $3, $4, $5)&quot;</span>,
<span class="comment">//payload.avg_traffic,</span>
<span class="ident">captcha_key</span>,
<span class="ident">username</span>,
<span class="ident">pattern</span>.<span class="ident">avg_traffic</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="ident">pattern</span>.<span class="ident">peak_sustainable_traffic</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="ident">pattern</span>.<span class="ident">broke_my_site_traffic</span>.<span class="ident">as_ref</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">v</span><span class="op">|</span> <span class="kw-2">*</span><span class="ident">v</span> <span class="kw">as</span> <span class="ident">i32</span>),
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// Get traffic configuration</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_traffic_pattern</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">TrafficPattern</span><span class="op">&gt;</span> {
<span class="kw">struct</span> <span class="ident">Traffic</span> {
<span class="ident">peak_sustainable_traffic</span>: <span class="ident">i32</span>,
<span class="ident">avg_traffic</span>: <span class="ident">i32</span>,
<span class="ident">broke_my_site_traffic</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">i32</span><span class="op">&gt;</span>,
}
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Traffic</span>,
<span class="string">&quot;SELECT
avg_traffic,
peak_sustainable_traffic,
broke_my_site_traffic
FROM
mcaptcha_sitekey_user_provided_avg_traffic
WHERE
config_id = (
SELECT
config_id
FROM
mcaptcha_config
WHERE
KEY = $1
AND user_id = (
SELECT
id
FROM
mcaptcha_users
WHERE
NAME = $2
)
)
&quot;</span>,
<span class="ident">captcha_key</span>,
<span class="ident">username</span>
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::TrafficPatternNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">TrafficPattern</span> {
<span class="ident">broke_my_site_traffic</span>: <span class="ident">res</span>.<span class="ident">broke_my_site_traffic</span>.<span class="ident">as_ref</span>().<span class="ident">map</span>(<span class="op">|</span><span class="ident">v</span><span class="op">|</span> <span class="kw-2">*</span><span class="ident">v</span> <span class="kw">as</span> <span class="ident">u32</span>),
<span class="ident">avg_traffic</span>: <span class="ident">res</span>.<span class="ident">avg_traffic</span> <span class="kw">as</span> <span class="ident">u32</span>,
<span class="ident">peak_sustainable_traffic</span>: <span class="ident">res</span>.<span class="ident">peak_sustainable_traffic</span> <span class="kw">as</span> <span class="ident">u32</span>,
})
}
<span class="doccomment">/// Delete traffic configuration</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">delete_traffic_pattern</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">captcha_key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;DELETE FROM mcaptcha_sitekey_user_provided_avg_traffic
WHERE config_id = (
SELECT config_id
FROM
mcaptcha_config
WHERE
key = ($1)
AND
user_id = (SELECT ID FROM mcaptcha_users WHERE name = $2)
);&quot;</span>,
<span class="ident">captcha_key</span>,
<span class="ident">username</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::TrafficPatternNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// create new notification</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">create_notification</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">p</span>: <span class="kw-2">&amp;</span><span class="ident">AddNotification</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">now</span> <span class="op">=</span> <span class="ident">now_unix_time_stamp</span>();
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_notifications (
heading, message, tx, rx, received)
VALUES (
$1, $2,
(SELECT ID FROM mcaptcha_users WHERE name = $3),
(SELECT ID FROM mcaptcha_users WHERE name = $4),
$5
);&quot;</span>,
<span class="ident">p</span>.<span class="ident">heading</span>,
<span class="ident">p</span>.<span class="ident">message</span>,
<span class="ident">p</span>.<span class="ident">from</span>,
<span class="ident">p</span>.<span class="ident">to</span>,
<span class="ident">now</span>
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="ident">map_register_err</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// get all unread notifications</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_all_unread_notifications</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Notification</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">inner_notifications</span> <span class="op">=</span> <span class="macro">sqlx::query_file_as!</span>(
<span class="ident">InnerNotification</span>,
<span class="string">&quot;./src/get_all_unread_notifications.sql&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::AccountNotFound</span>))<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">Vec::with_capacity</span>(<span class="ident">inner_notifications</span>.<span class="ident">len</span>());
<span class="ident">inner_notifications</span>
.<span class="ident">drain</span>(<span class="number">0</span>..)
.<span class="ident">for_each</span>(<span class="op">|</span><span class="ident">n</span><span class="op">|</span> <span class="ident">notifications</span>.<span class="ident">push</span>(<span class="ident">n</span>.<span class="ident">into</span>()));
<span class="prelude-val">Ok</span>(<span class="ident">notifications</span>)
}
<span class="doccomment">/// mark a notification read</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">mark_notification_read</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">id</span>: <span class="ident">i32</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="macro">sqlx::query_file_as!</span>(
<span class="ident">Notification</span>,
<span class="string">&quot;./src/mark_notification_read.sql&quot;</span>,
<span class="ident">id</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::NotificationNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// record PoWConfig fetches</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">record_fetch</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">now</span> <span class="op">=</span> <span class="ident">now_unix_time_stamp</span>();
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_pow_fetched_stats
(config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1), $2)&quot;</span>,
<span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">now</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// record PoWConfig solves</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">record_solve</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">now</span> <span class="op">=</span> <span class="ident">OffsetDateTime::now_utc</span>();
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_pow_solved_stats
(config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1), $2)&quot;</span>,
<span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">now</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// record PoWConfig confirms</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">record_confirm</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">now</span> <span class="op">=</span> <span class="ident">now_unix_time_stamp</span>();
<span class="kw">let</span> <span class="kw">_</span> <span class="op">=</span> <span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_pow_confirmed_stats
(config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1), $2)&quot;</span>,
<span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">now</span>
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="doccomment">/// featch PoWConfig fetches</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch_config_fetched</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">user</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">records</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Date</span>,
<span class="string">&quot;SELECT time FROM mcaptcha_pow_fetched_stats
WHERE
config_id = (
SELECT
config_id FROM mcaptcha_config
WHERE
key = $1
AND
user_id = (
SELECT
ID FROM mcaptcha_users WHERE name = $2))
ORDER BY time DESC&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">user</span>,
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">Date::dates_to_unix</span>(<span class="ident">records</span>))
}
<span class="doccomment">/// featch PoWConfig solves</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch_solve</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">user</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">records</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Date</span>,
<span class="string">&quot;SELECT time FROM mcaptcha_pow_solved_stats
WHERE config_id = (
SELECT config_id FROM mcaptcha_config
WHERE
key = $1
AND
user_id = (
SELECT
ID FROM mcaptcha_users WHERE name = $2))
ORDER BY time DESC&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">user</span>
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">Date::dates_to_unix</span>(<span class="ident">records</span>))
}
<span class="doccomment">/// featch PoWConfig confirms</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch_confirm</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">user</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">records</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Date</span>,
<span class="string">&quot;SELECT time FROM mcaptcha_pow_confirmed_stats
WHERE
config_id = (
SELECT config_id FROM mcaptcha_config
WHERE
key = $1
AND
user_id = (
SELECT
ID FROM mcaptcha_users WHERE name = $2))
ORDER BY time DESC&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">user</span>
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="self">self</span>.<span class="ident">pool</span>)
.<span class="kw">await</span>
.<span class="ident">map_err</span>(<span class="op">|</span><span class="ident">e</span><span class="op">|</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>, <span class="ident">DBError::CaptchaNotFound</span>))<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">Date::dates_to_unix</span>(<span class="ident">records</span>))
}
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">Date</span> {
<span class="ident">time</span>: <span class="ident">OffsetDateTime</span>,
}
<span class="kw">impl</span> <span class="ident">Date</span> {
<span class="kw">fn</span> <span class="ident">dates_to_unix</span>(<span class="kw-2">mut</span> <span class="ident">d</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="self">Self</span><span class="op">&gt;</span>) -&gt; <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">dates</span> <span class="op">=</span> <span class="ident">Vec::with_capacity</span>(<span class="ident">d</span>.<span class="ident">len</span>());
<span class="ident">d</span>.<span class="ident">drain</span>(<span class="number">0</span>..)
.<span class="ident">for_each</span>(<span class="op">|</span><span class="ident">x</span><span class="op">|</span> <span class="ident">dates</span>.<span class="ident">push</span>(<span class="ident">x</span>.<span class="ident">time</span>.<span class="ident">unix_timestamp</span>()));
<span class="ident">dates</span>
}
}
<span class="kw">fn</span> <span class="ident">now_unix_time_stamp</span>() -&gt; <span class="ident">OffsetDateTime</span> {
<span class="ident">OffsetDateTime::now_utc</span>()
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Default</span>, <span class="ident">PartialEq</span>)]</span>
<span class="doccomment">/// Represents notification</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">InnerNotification</span> {
<span class="doccomment">/// receiver name of the notification</span>
<span class="kw">pub</span> <span class="ident">name</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>,
<span class="doccomment">/// heading of the notification</span>
<span class="kw">pub</span> <span class="ident">heading</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>,
<span class="doccomment">/// message of the notification</span>
<span class="kw">pub</span> <span class="ident">message</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>,
<span class="doccomment">/// when notification was received</span>
<span class="kw">pub</span> <span class="ident">received</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">OffsetDateTime</span><span class="op">&gt;</span>,
<span class="doccomment">/// db assigned ID of the notification</span>
<span class="kw">pub</span> <span class="ident">id</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">i32</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">InnerNotification</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">Notification</span> {
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">n</span>: <span class="ident">InnerNotification</span>) -&gt; <span class="self">Self</span> {
<span class="ident">Notification</span> {
<span class="ident">name</span>: <span class="ident">n</span>.<span class="ident">name</span>,
<span class="ident">heading</span>: <span class="ident">n</span>.<span class="ident">heading</span>,
<span class="ident">message</span>: <span class="ident">n</span>.<span class="ident">message</span>,
<span class="ident">received</span>: <span class="ident">n</span>.<span class="ident">received</span>.<span class="ident">map</span>(<span class="op">|</span><span class="ident">t</span><span class="op">|</span> <span class="ident">t</span>.<span class="ident">unix_timestamp</span>()),
<span class="ident">id</span>: <span class="ident">n</span>.<span class="ident">id</span>,
}
}
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">InternaleCaptchaConfig</span> {
<span class="ident">config_id</span>: <span class="ident">i32</span>,
<span class="ident">duration</span>: <span class="ident">i32</span>,
<span class="ident">name</span>: <span class="ident">String</span>,
<span class="ident">key</span>: <span class="ident">String</span>,
}
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">InternaleCaptchaConfig</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">Captcha</span> {
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">i</span>: <span class="ident">InternaleCaptchaConfig</span>) -&gt; <span class="self">Self</span> {
<span class="self">Self</span> {
<span class="ident">config_id</span>: <span class="ident">i</span>.<span class="ident">config_id</span>,
<span class="ident">duration</span>: <span class="ident">i</span>.<span class="ident">duration</span>,
<span class="ident">description</span>: <span class="ident">i</span>.<span class="ident">name</span>,
<span class="ident">key</span>: <span class="ident">i</span>.<span class="ident">key</span>,
}
}
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="db_sqlx_postgres" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>