Deploying to gh-pages from @ 3710c8f653 🚀

This commit is contained in:
realaravinth
2022-05-27 13:55:17 +00:00
parent d4575e7ebf
commit 0cad395013
608 changed files with 13753 additions and 4723 deletions

130
src/db_core/errors.rs.html Normal file
View File

@@ -0,0 +1,130 @@
<!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-core/src/errors.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>errors.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_core/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_core/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_core/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>
</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="doccomment">//! represents all the ways a trait can fail using this crate</span>
<span class="kw">use</span> <span class="ident">std::error::Error</span> <span class="kw">as</span> <span class="ident">StdError</span>;
<span class="comment">//use derive_more::{error, Error as DeriveError};</span>
<span class="kw">use</span> <span class="ident">thiserror::Error</span>;
<span class="doccomment">/// Error data structure grouping various error subtypes</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Error</span>)]</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">DBError</span> {
<span class="doccomment">/// errors that are specific to a database implementation</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;{0}&quot;</span>)]</span>
<span class="ident">DBError</span>(<span class="attribute">#[<span class="ident">source</span>]</span> <span class="ident">BoxDynError</span>),
<span class="doccomment">/// Username is taken</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Username is taken&quot;</span>)]</span>
<span class="ident">UsernameTaken</span>,
<span class="doccomment">/// Email is taken</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Email is taken&quot;</span>)]</span>
<span class="ident">EmailTaken</span>,
<span class="doccomment">/// Secret is taken</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Secret is taken&quot;</span>)]</span>
<span class="ident">SecretTaken</span>,
<span class="doccomment">/// Captcha key is taken</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Captcha key is taken&quot;</span>)]</span>
<span class="ident">CaptchaKeyTaken</span>,
<span class="doccomment">/// Account not found</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Account not found&quot;</span>)]</span>
<span class="ident">AccountNotFound</span>,
<span class="doccomment">/// Captcha not found</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Captcha not found&quot;</span>)]</span>
<span class="ident">CaptchaNotFound</span>,
<span class="doccomment">/// Traffic pattern not found</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Traffic pattern not found&quot;</span>)]</span>
<span class="ident">TrafficPatternNotFound</span>,
<span class="doccomment">/// Notification not found</span>
<span class="attribute">#[<span class="ident">error</span>(<span class="string">&quot;Notification not found&quot;</span>)]</span>
<span class="ident">NotificationNotFound</span>,
}
<span class="doccomment">/// Convenience type alias for grouping driver-specific errors</span>
<span class="kw">pub</span> <span class="kw">type</span> <span class="ident">BoxDynError</span> <span class="op">=</span> <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">StdError</span> <span class="op">+</span> <span class="lifetime">&#39;static</span> <span class="op">+</span> <span class="ident">Send</span> <span class="op">+</span> <span class="ident">Sync</span><span class="op">&gt;</span>;
<span class="doccomment">/// Generic result data structure</span>
<span class="kw">pub</span> <span class="kw">type</span> <span class="ident">DBResult</span><span class="op">&lt;</span><span class="ident">V</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">std::result::Result</span><span class="op">&lt;</span><span class="ident">V</span>, <span class="ident">DBError</span><span class="op">&gt;</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_core" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

712
src/db_core/lib.rs.html Normal file
View File

@@ -0,0 +1,712 @@
<!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-core/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_core/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_core/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_core/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>
</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="attribute">#![<span class="ident">warn</span>(<span class="ident">missing_docs</span>)]</span>
<span class="doccomment">//! # `mCaptcha` database operations</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! Traits and datastructures used in mCaptcha to interact with database.</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! To use an unsupported database with mCaptcha, traits present within this crate should be</span>
<span class="doccomment">//! implemented.</span>
<span class="doccomment">//!</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! ## Organisation</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! Database functionallity is divided accross various modules:</span>
<span class="doccomment">//!</span>
<span class="doccomment">//! - [errors](crate::auth): error data structures used in this crate</span>
<span class="doccomment">//! - [ops](crate::ops): meta operations like connection pool creation, migrations and getting</span>
<span class="doccomment">//! connection from pool</span>
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">libmcaptcha::defense::Level</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">errors</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">ops</span>;
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">feature</span> <span class="op">=</span> <span class="string">&quot;test&quot;</span>)]</span>
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span>;
<span class="kw">use</span> <span class="ident">dev</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">ops::GetConnection</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">prelude</span> {
<span class="doccomment">//! useful imports for users working with a supported database</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>::ops</span>::<span class="kw-2">*</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">mod</span> <span class="ident">dev</span> {
<span class="doccomment">//! useful imports for supporting a new database</span>
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident"><span class="kw">super</span>::prelude</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">async_trait::async_trait</span>;
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>, <span class="ident">PartialEq</span>)]</span>
<span class="doccomment">/// Data required to register a new user</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Register</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// username of new user</span>
<span class="kw">pub</span> <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// secret of new user</span>
<span class="kw">pub</span> <span class="ident">secret</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// hashed password of new use</span>
<span class="kw">pub</span> <span class="ident">hash</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// Optionally, email of new use</span>
<span class="kw">pub</span> <span class="ident">email</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span><span class="op">&gt;</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>, <span class="ident">PartialEq</span>)]</span>
<span class="doccomment">/// data required to update them email of a user</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">UpdateEmail</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// username of the user</span>
<span class="kw">pub</span> <span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// new email address of the user</span>
<span class="kw">pub</span> <span class="ident">new_email</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>, <span class="ident">PartialEq</span>)]</span>
<span class="doccomment">/// types of credentials used as identifiers during login</span>
<span class="kw">pub</span> <span class="kw">enum</span> <span class="ident">Login</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// username as login</span>
<span class="ident">Username</span>(<span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>),
<span class="doccomment">/// email as login</span>
<span class="ident">Email</span>(<span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>),
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>, <span class="ident">PartialEq</span>)]</span>
<span class="doccomment">/// type encapsulating username and hashed password of a user</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">NameHash</span> {
<span class="doccomment">/// username</span>
<span class="kw">pub</span> <span class="ident">username</span>: <span class="ident">String</span>,
<span class="doccomment">/// hashed password</span>
<span class="kw">pub</span> <span class="ident">hash</span>: <span class="ident">String</span>,
}
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="doccomment">/// mCaptcha&#39;s database requirements. To implement support for $Database, kindly implement this</span>
<span class="doccomment">/// trait.</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">MCDatabase</span>: <span class="ident">std::marker::Send</span> <span class="op">+</span> <span class="ident">std::marker::Sync</span> <span class="op">+</span> <span class="ident">CloneSPDatabase</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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="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="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Default</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>, <span class="ident">PartialEq</span>)]</span>
<span class="doccomment">/// Captcha statistics with time recorded in UNIX epoch formats</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">StatsUnixTimestamp</span> {
<span class="doccomment">/// times at which the configuration were fetched</span>
<span class="kw">pub</span> <span class="ident">config_fetches</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
<span class="doccomment">/// times at which the PoW was solved</span>
<span class="kw">pub</span> <span class="ident">solves</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
<span class="doccomment">/// times at which the PoW token was verified</span>
<span class="kw">pub</span> <span class="ident">confirms</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</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">Deserialize</span>, <span class="ident">Serialize</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">Notification</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">i64</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="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 class="ident">Serialize</span>, <span class="ident">Deserialize</span>)]</span>
<span class="doccomment">/// Data required to add notification</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">AddNotification</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// who is the notification addressed to?</span>
<span class="kw">pub</span> <span class="ident">to</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// notification sender</span>
<span class="kw">pub</span> <span class="ident">from</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// heading of the notification</span>
<span class="kw">pub</span> <span class="ident">heading</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// mesage of the notification</span>
<span class="kw">pub</span> <span class="ident">message</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Default</span>, <span class="ident">PartialEq</span>, <span class="ident">Serialize</span>, <span class="ident">Deserialize</span>, <span class="ident">Clone</span>, <span class="ident">Debug</span>)]</span>
<span class="doccomment">/// User&#39;s traffic pattern; used in generating a captcha configuration</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">TrafficPattern</span> {
<span class="doccomment">/// average traffic of user&#39;s website</span>
<span class="kw">pub</span> <span class="ident">avg_traffic</span>: <span class="ident">u32</span>,
<span class="doccomment">/// the peak traffic that the user&#39;s website can handle</span>
<span class="kw">pub</span> <span class="ident">peak_sustainable_traffic</span>: <span class="ident">u32</span>,
<span class="doccomment">/// trafic that bought the user&#39;s website down; optional</span>
<span class="kw">pub</span> <span class="ident">broke_my_site_traffic</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">u32</span><span class="op">&gt;</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Default</span>, <span class="ident">PartialEq</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="doccomment">/// data requried to create new captcha</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">CreateCaptcha</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="doccomment">/// cool down duration</span>
<span class="kw">pub</span> <span class="ident">duration</span>: <span class="ident">i32</span>,
<span class="doccomment">/// description of the captcha</span>
<span class="kw">pub</span> <span class="ident">description</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="doccomment">/// secret key of the captcha</span>
<span class="kw">pub</span> <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Default</span>, <span class="ident">PartialEq</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="doccomment">/// Data representing a captcha</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Captcha</span> {
<span class="doccomment">/// Database assigned ID</span>
<span class="kw">pub</span> <span class="ident">config_id</span>: <span class="ident">i32</span>,
<span class="doccomment">/// cool down duration</span>
<span class="kw">pub</span> <span class="ident">duration</span>: <span class="ident">i32</span>,
<span class="doccomment">/// description of the captcha</span>
<span class="kw">pub</span> <span class="ident">description</span>: <span class="ident">String</span>,
<span class="doccomment">/// secret key of the captcha</span>
<span class="kw">pub</span> <span class="ident">key</span>: <span class="ident">String</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Deserialize</span>, <span class="ident">PartialEq</span>, <span class="ident">Default</span>, <span class="ident">Serialize</span>)]</span>
<span class="doccomment">/// datastructure representing a user&#39;s secret</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Secret</span> {
<span class="doccomment">/// user&#39;s secret</span>
<span class="kw">pub</span> <span class="ident">secret</span>: <span class="ident">String</span>,
}
<span class="doccomment">/// Trait to clone MCDatabase</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">CloneSPDatabase</span> {
<span class="doccomment">/// clone DB</span>
<span class="kw">fn</span> <span class="ident">clone_db</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">MCDatabase</span><span class="op">&gt;</span>;
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">T</span><span class="op">&gt;</span> <span class="ident">CloneSPDatabase</span> <span class="kw">for</span> <span class="ident">T</span>
<span class="kw">where</span>
<span class="ident">T</span>: <span class="ident">MCDatabase</span> <span class="op">+</span> <span class="ident">Clone</span> <span class="op">+</span> <span class="lifetime">&#39;static</span>,
{
<span class="kw">fn</span> <span class="ident">clone_db</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">MCDatabase</span><span class="op">&gt;</span> {
<span class="ident">Box::new</span>(<span class="self">self</span>.<span class="ident">clone</span>())
}
}
<span class="kw">impl</span> <span class="ident">Clone</span> <span class="kw">for</span> <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">MCDatabase</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">clone</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="self">Self</span> {
(<span class="kw-2">*</span><span class="kw-2">*</span><span class="self">self</span>).<span class="ident">clone_db</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_core" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

106
src/db_core/ops.rs.html Normal file
View File

@@ -0,0 +1,106 @@
<!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-core/src/ops.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>ops.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_core/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_core/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_core/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>
</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="doccomment">//! meta operations like migration and connecting to a database</span>
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::dev</span>::<span class="kw-2">*</span>;
<span class="doccomment">/// Database operations trait(migrations, pool creation and fetching connection from pool)</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">DBOps</span>: <span class="ident">GetConnection</span> <span class="op">+</span> <span class="ident">Migrate</span> {}
<span class="doccomment">/// Get database connection</span>
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">GetConnection</span> {
<span class="doccomment">/// database connection type</span>
<span class="kw">type</span> <span class="ident">Conn</span>;
<span class="doccomment">/// database specific error-type</span>
<span class="doccomment">/// get connection from connection pool</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_conn</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="ident"><span class="self">Self</span>::Conn</span><span class="op">&gt;</span>;
}
<span class="doccomment">/// Create databse connection</span>
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">Connect</span> {
<span class="doccomment">/// database specific pool-type</span>
<span class="kw">type</span> <span class="ident">Pool</span>: <span class="ident">MCDatabase</span>;
<span class="doccomment">/// database specific error-type</span>
<span class="doccomment">/// create connection pool</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="doccomment">/// database migrations</span>
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">Migrate</span>: <span class="ident">MCDatabase</span> {
<span class="doccomment">/// database specific error-type</span>
<span class="doccomment">/// run migrations</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>;
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="db_core" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

576
src/db_core/tests.rs.html Normal file
View File

@@ -0,0 +1,576 @@
<!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-core/src/tests.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>tests.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_core/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_core/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_core/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>
</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="doccomment">//! Test utilities</span>
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::prelude</span>::<span class="kw-2">*</span>;
<span class="doccomment">/// test all database functions</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">database_works</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span>, <span class="ident">T</span>: <span class="ident">MCDatabase</span><span class="op">&gt;</span>(
<span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">T</span>,
<span class="ident">p</span>: <span class="kw-2">&amp;</span><span class="ident">Register</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>,
<span class="ident">c</span>: <span class="kw-2">&amp;</span><span class="ident">CreateCaptcha</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>,
<span class="ident">l</span>: <span class="kw-2">&amp;</span>[<span class="ident">Level</span>],
<span class="ident">tp</span>: <span class="kw-2">&amp;</span><span class="ident">TrafficPattern</span>,
<span class="ident">an</span>: <span class="kw-2">&amp;</span><span class="ident">AddNotification</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>,
) {
<span class="macro">assert!</span>(<span class="ident">db</span>.<span class="ident">ping</span>().<span class="kw">await</span>, <span class="string">&quot;ping test&quot;</span>);
<span class="kw">if</span> <span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>() {
<span class="ident">db</span>.<span class="ident">delete_user</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert!</span>(
<span class="op">!</span><span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user is deleted so username shouldn&#39;t exsit&quot;</span>
);
}
<span class="ident">db</span>.<span class="ident">register</span>(<span class="ident">p</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="comment">// testing get secret</span>
<span class="kw">let</span> <span class="ident">secret</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_secret</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">secret</span>.<span class="ident">secret</span>, <span class="ident">p</span>.<span class="ident">secret</span>, <span class="string">&quot;user secret matches&quot;</span>);
<span class="comment">// testing update secret: setting secret = username</span>
<span class="ident">db</span>.<span class="ident">update_secret</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">secret</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_secret</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(
<span class="ident">secret</span>.<span class="ident">secret</span>, <span class="ident">p</span>.<span class="ident">username</span>,
<span class="string">&quot;user secret matches username; as set by previous step&quot;</span>
);
<span class="comment">// testing get_password</span>
<span class="comment">// with username</span>
<span class="kw">let</span> <span class="ident">name_hash</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">Login::Username</span>(<span class="ident">p</span>.<span class="ident">username</span>)).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">name_hash</span>.<span class="ident">hash</span>, <span class="ident">p</span>.<span class="ident">hash</span>, <span class="string">&quot;user password matches&quot;</span>);
<span class="macro">assert_eq!</span>(<span class="ident">name_hash</span>.<span class="ident">username</span>, <span class="ident">p</span>.<span class="ident">username</span>, <span class="string">&quot;username matches&quot;</span>);
<span class="comment">// with email</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">name_hash</span> <span class="op">=</span> <span class="ident">db</span>
.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">Login::Email</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()))
.<span class="kw">await</span>
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">name_hash</span>.<span class="ident">hash</span>, <span class="ident">p</span>.<span class="ident">hash</span>, <span class="string">&quot;user password matches&quot;</span>);
<span class="macro">assert_eq!</span>(<span class="ident">name_hash</span>.<span class="ident">username</span>, <span class="ident">p</span>.<span class="ident">username</span>, <span class="string">&quot;username matches&quot;</span>);
<span class="comment">// testing get_email</span>
<span class="macro">assert_eq!</span>(
<span class="ident">db</span>.<span class="ident">get_email</span>(<span class="ident">p</span>.<span class="ident">username</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>()
.<span class="ident">as_ref</span>()
.<span class="ident">unwrap</span>()
.<span class="ident">as_str</span>(),
<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">unwrap</span>()
);
<span class="comment">// testing email exists</span>
<span class="macro">assert!</span>(
<span class="ident">db</span>.<span class="ident">email_exists</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user is registered so email should exsit&quot;</span>
);
<span class="macro">assert!</span>(
<span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user is registered so username should exsit&quot;</span>
);
<span class="comment">// update password test. setting password = username</span>
<span class="ident">name_hash</span>.<span class="ident">hash</span> <span class="op">=</span> <span class="ident">name_hash</span>.<span class="ident">username</span>.<span class="ident">clone</span>();
<span class="ident">db</span>.<span class="ident">update_password</span>(<span class="kw-2">&amp;</span><span class="ident">name_hash</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">name_hash</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">Login::Username</span>(<span class="ident">p</span>.<span class="ident">username</span>)).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(
<span class="ident">name_hash</span>.<span class="ident">hash</span>, <span class="ident">p</span>.<span class="ident">username</span>,
<span class="string">&quot;user password matches with changed value&quot;</span>
);
<span class="macro">assert_eq!</span>(<span class="ident">name_hash</span>.<span class="ident">username</span>, <span class="ident">p</span>.<span class="ident">username</span>, <span class="string">&quot;username matches&quot;</span>);
<span class="comment">// update username to p.email</span>
<span class="macro">assert!</span>(
<span class="op">!</span><span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user with p.email doesn&#39;t exist. pre-check to update username to p.email&quot;</span>
);
<span class="ident">db</span>.<span class="ident">update_username</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>())
.<span class="kw">await</span>
.<span class="ident">unwrap</span>();
<span class="macro">assert!</span>(
<span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user with p.email exist post-update&quot;</span>
);
<span class="comment">// deleting user for re-registration with email = None</span>
<span class="ident">db</span>.<span class="ident">delete_user</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert!</span>(
<span class="op">!</span><span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user is deleted so username shouldn&#39;t exsit&quot;</span>
);
<span class="comment">// register with email = None</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">p2</span> <span class="op">=</span> <span class="ident">p</span>.<span class="ident">clone</span>();
<span class="ident">p2</span>.<span class="ident">email</span> <span class="op">=</span> <span class="prelude-val">None</span>;
<span class="ident">db</span>.<span class="ident">register</span>(<span class="kw-2">&amp;</span><span class="ident">p2</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert!</span>(
<span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="ident">p2</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user is registered so username should exsit&quot;</span>
);
<span class="macro">assert!</span>(
<span class="op">!</span><span class="ident">db</span>.<span class="ident">email_exists</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user registration with email is deleted; so email shouldn&#39;t exsit&quot;</span>
);
<span class="comment">// testing get_email = None</span>
<span class="macro">assert_eq!</span>(<span class="ident">db</span>.<span class="ident">get_email</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>(), <span class="prelude-val">None</span>);
<span class="comment">// testing update email</span>
<span class="kw">let</span> <span class="ident">update_email</span> <span class="op">=</span> <span class="ident">UpdateEmail</span> {
<span class="ident">username</span>: <span class="ident">p</span>.<span class="ident">username</span>,
<span class="ident">new_email</span>: <span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>(),
};
<span class="ident">db</span>.<span class="ident">update_email</span>(<span class="kw-2">&amp;</span><span class="ident">update_email</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">println!</span>(
<span class="string">&quot;null user email: {}&quot;</span>,
<span class="ident">db</span>.<span class="ident">email_exists</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>()
);
<span class="macro">assert!</span>(
<span class="ident">db</span>.<span class="ident">email_exists</span>(<span class="ident">p</span>.<span class="ident">email</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>()).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="string">&quot;user was with empty email but email is set; so email should exsit&quot;</span>
);
<span class="comment">/*
* test notification workflows
* 1. Add notifications: a minimum of two, to mark as read and test if it has affected it
* 2. Get unread notifications
* 3. Mark a notification read, check if it has affected Step #2
*/</span>
<span class="comment">// 1. add notification</span>
<span class="ident">db</span>.<span class="ident">create_notification</span>(<span class="ident">an</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="ident">db</span>.<span class="ident">create_notification</span>(<span class="ident">an</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="comment">// 2. Get notifications</span>
<span class="kw">let</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_all_unread_notifications</span>(<span class="ident">an</span>.<span class="ident">to</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">notifications</span>.<span class="ident">len</span>(), <span class="number">2</span>);
<span class="macro">assert_eq!</span>(<span class="ident">notifications</span>[<span class="number">0</span>].<span class="ident">heading</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>(), <span class="ident">an</span>.<span class="ident">heading</span>);
<span class="comment">// 3. mark a notification read</span>
<span class="ident">db</span>.<span class="ident">mark_notification_read</span>(<span class="ident">an</span>.<span class="ident">to</span>, <span class="ident">notifications</span>[<span class="number">0</span>].<span class="ident">id</span>.<span class="ident">unwrap</span>())
.<span class="kw">await</span>
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">new_notifications</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_all_unread_notifications</span>(<span class="ident">an</span>.<span class="ident">to</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">new_notifications</span>.<span class="ident">len</span>(), <span class="number">1</span>);
<span class="comment">// create captcha</span>
<span class="ident">db</span>.<span class="ident">create_captcha</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert!</span>(<span class="ident">db</span>.<span class="ident">captcha_exists</span>(<span class="prelude-val">None</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>());
<span class="macro">assert!</span>(<span class="ident">db</span>.<span class="ident">captcha_exists</span>(<span class="prelude-val">Some</span>(<span class="ident">p</span>.<span class="ident">username</span>), <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>());
<span class="comment">// get captcha configuration</span>
<span class="kw">let</span> <span class="ident">captcha</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_captcha_config</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">captcha</span>.<span class="ident">key</span>, <span class="ident">c</span>.<span class="ident">key</span>);
<span class="macro">assert_eq!</span>(<span class="ident">captcha</span>.<span class="ident">duration</span>, <span class="ident">c</span>.<span class="ident">duration</span>);
<span class="macro">assert_eq!</span>(<span class="ident">captcha</span>.<span class="ident">description</span>, <span class="ident">c</span>.<span class="ident">description</span>);
<span class="comment">// get all captchas that belong to user</span>
<span class="kw">let</span> <span class="ident">all_user_captchas</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_all_user_captchas</span>(<span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">all_user_captchas</span>.<span class="ident">len</span>(), <span class="number">1</span>);
<span class="macro">assert_eq!</span>(<span class="ident">all_user_captchas</span>[<span class="number">0</span>], <span class="ident">captcha</span>);
<span class="comment">// get captcha cooldown duration</span>
<span class="macro">assert_eq!</span>(<span class="ident">db</span>.<span class="ident">get_captcha_cooldown</span>(<span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>(), <span class="ident">c</span>.<span class="ident">duration</span>);
<span class="comment">// add traffic pattern</span>
<span class="ident">db</span>.<span class="ident">add_traffic_pattern</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>, <span class="ident">tp</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(
<span class="kw-2">&amp;</span><span class="ident">db</span>.<span class="ident">get_traffic_pattern</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>(),
<span class="ident">tp</span>
);
<span class="comment">// delete traffic pattern</span>
<span class="ident">db</span>.<span class="ident">delete_traffic_pattern</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert!</span>(
<span class="macro">matches!</span>(
<span class="ident">db</span>.<span class="ident">get_traffic_pattern</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>,
<span class="prelude-val">Err</span>(<span class="ident">DBError::TrafficPatternNotFound</span>)
),
<span class="string">&quot;deletion successful; traffic pattern no longer exists&quot;</span>
);
<span class="comment">// add captcha levels</span>
<span class="ident">db</span>.<span class="ident">add_captcha_levels</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>, <span class="ident">l</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="comment">// get captcha levels with username</span>
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">db</span>
.<span class="ident">get_captcha_levels</span>(<span class="prelude-val">Some</span>(<span class="ident">p</span>.<span class="ident">username</span>), <span class="ident">c</span>.<span class="ident">key</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">levels</span>, <span class="ident">l</span>);
<span class="comment">// get captcha levels without username</span>
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">db</span>.<span class="ident">get_captcha_levels</span>(<span class="prelude-val">None</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">levels</span>, <span class="ident">l</span>);
<span class="comment">/*
* Test stats
* 1. record fetch config
* 2. record solve
* 3. record token verify
* 4. fetch config fetches
* 5. fetch solves
* 6. fetch token verify
*/</span>
<span class="macro">assert!</span>(<span class="ident">db</span>
.<span class="ident">fetch_config_fetched</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>()
.<span class="ident">is_empty</span>());
<span class="macro">assert!</span>(<span class="ident">db</span>.<span class="ident">fetch_solve</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>().<span class="ident">is_empty</span>());
<span class="macro">assert!</span>(<span class="ident">db</span>
.<span class="ident">fetch_confirm</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>()
.<span class="ident">is_empty</span>());
<span class="ident">db</span>.<span class="ident">record_fetch</span>(<span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="ident">db</span>.<span class="ident">record_solve</span>(<span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="ident">db</span>.<span class="ident">record_confirm</span>(<span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">db</span>.<span class="ident">fetch_solve</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>().<span class="ident">len</span>(), <span class="number">1</span>);
<span class="macro">assert_eq!</span>(
<span class="ident">db</span>.<span class="ident">fetch_config_fetched</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>()
.<span class="ident">len</span>(),
<span class="number">1</span>
);
<span class="macro">assert_eq!</span>(<span class="ident">db</span>.<span class="ident">fetch_solve</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>().<span class="ident">len</span>(), <span class="number">1</span>);
<span class="macro">assert_eq!</span>(<span class="ident">db</span>.<span class="ident">fetch_confirm</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>().<span class="ident">len</span>(), <span class="number">1</span>);
<span class="comment">// update captcha key; set key = username;</span>
<span class="ident">db</span>.<span class="ident">update_captcha_key</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>, <span class="ident">p</span>.<span class="ident">username</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>();
<span class="comment">// checking for captcha with old key; shouldn&#39;t exist</span>
<span class="macro">assert!</span>(<span class="op">!</span><span class="ident">db</span>.<span class="ident">captcha_exists</span>(<span class="prelude-val">Some</span>(<span class="ident">p</span>.<span class="ident">username</span>), <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>());
<span class="comment">// checking for captcha with new key; shouldn exist</span>
<span class="macro">assert!</span>(<span class="ident">db</span>
.<span class="ident">captcha_exists</span>(<span class="prelude-val">Some</span>(<span class="ident">p</span>.<span class="ident">username</span>), <span class="ident">p</span>.<span class="ident">username</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>());
<span class="comment">// delete captcha levels</span>
<span class="ident">db</span>.<span class="ident">delete_captcha_levels</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="comment">// update captcha; set description = username and duration *= duration;</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">c2</span> <span class="op">=</span> <span class="ident">c</span>.<span class="ident">clone</span>();
<span class="ident">c2</span>.<span class="ident">duration</span> <span class="kw-2">*</span><span class="op">=</span> <span class="ident">c2</span>.<span class="ident">duration</span>;
<span class="ident">c2</span>.<span class="ident">description</span> <span class="op">=</span> <span class="ident">p</span>.<span class="ident">username</span>;
<span class="ident">db</span>.<span class="ident">update_captcha_metadata</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">c2</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="comment">// delete captcha; updated key = p.username so invoke delete with it</span>
<span class="ident">db</span>.<span class="ident">delete_captcha</span>(<span class="ident">p</span>.<span class="ident">username</span>, <span class="ident">p</span>.<span class="ident">username</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert!</span>(<span class="op">!</span><span class="ident">db</span>.<span class="ident">captcha_exists</span>(<span class="prelude-val">Some</span>(<span class="ident">p</span>.<span class="ident">username</span>), <span class="ident">c</span>.<span class="ident">key</span>).<span class="kw">await</span>.<span class="ident">unwrap</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_core" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

View File

@@ -0,0 +1,120 @@
<!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/errors.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>errors.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>
</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="doccomment">//! Error-handling utilities</span>
<span class="kw">use</span> <span class="ident">std::borrow::Cow</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::Error</span>;
<span class="doccomment">/// map custom row not found error to DB error</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">map_row_not_found_err</span>(<span class="ident">e</span>: <span class="ident">Error</span>, <span class="ident">row_not_found</span>: <span class="ident">DBError</span>) -&gt; <span class="ident">DBError</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="ident">Error::RowNotFound</span> <span class="op">=</span> <span class="ident">e</span> {
<span class="ident">row_not_found</span>
} <span class="kw">else</span> {
<span class="ident">map_register_err</span>(<span class="ident">e</span>)
}
}
<span class="doccomment">/// map postgres errors to [DBError](DBError) types</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">map_register_err</span>(<span class="ident">e</span>: <span class="ident">Error</span>) -&gt; <span class="ident">DBError</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="ident">Error::Database</span>(<span class="ident">err</span>) <span class="op">=</span> <span class="ident">e</span> {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>)) {
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">err</span>.<span class="ident">message</span>();
<span class="macro">println!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">msg</span>);
<span class="kw">if</span> <span class="ident">msg</span>.<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_name_key&quot;</span>) {
<span class="ident">DBError::UsernameTaken</span>
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">msg</span>.<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_email_key&quot;</span>) {
<span class="ident">DBError::EmailTaken</span>
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">msg</span>.<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_secret_key&quot;</span>) {
<span class="ident">DBError::SecretTaken</span>
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">msg</span>.<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_config_key_key&quot;</span>) {
<span class="ident">DBError::CaptchaKeyTaken</span>
} <span class="kw">else</span> {
<span class="ident">DBError::DBError</span>(<span class="ident">Box::new</span>(<span class="ident">Error::Database</span>(<span class="ident">err</span>)))
}
} <span class="kw">else</span> {
<span class="ident">DBError::DBError</span>(<span class="ident">Box::new</span>(<span class="ident">Error::Database</span>(<span class="ident">err</span>)))
}
} <span class="kw">else</span> {
<span class="ident">DBError::DBError</span>(<span class="ident">Box::new</span>(<span class="ident">e</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>

File diff suppressed because it is too large Load Diff

View File

@@ -22,21 +22,21 @@
<span id="17">17</span>
<span id="18">18</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>
* 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">pub</span> <span class="kw">mod</span> <span class="ident">v1</span>;
</code></pre></div>

View File

@@ -67,34 +67,22 @@
<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>
</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>
* 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">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
@@ -113,30 +101,20 @@
<span class="ident">data</span>: <span class="ident">AppData</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">use</span> <span class="ident">argon2_creds::Config</span>;
<span class="kw">use</span> <span class="ident">sqlx::Error::RowNotFound</span>;
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">rec</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Password</span>,
<span class="string">r#&quot;SELECT password FROM mcaptcha_users WHERE name = ($1)&quot;#</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">hash</span> <span class="op">=</span> <span class="ident">data</span>
.<span class="ident">db</span>
.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">db_core::Login::Username</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>))
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">match</span> <span class="ident">rec</span> {
<span class="prelude-val">Ok</span>(<span class="ident">s</span>) =&gt; {
<span class="kw">if</span> <span class="ident">Config::verify</span>(<span class="kw-2">&amp;</span><span class="ident">s</span>.<span class="ident">password</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span> {
<span class="ident">runners::delete_user</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">id</span>.<span class="ident">forget</span>();
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
} <span class="kw">else</span> {
<span class="prelude-val">Err</span>(<span class="ident">ServiceError::WrongPassword</span>)
}
}
<span class="prelude-val">Err</span>(<span class="ident">RowNotFound</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::AccountNotFound</span>),
<span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::InternalServerError</span>),
<span class="kw">if</span> <span class="ident">Config::verify</span>(<span class="kw-2">&amp;</span><span class="ident">hash</span>.<span class="ident">hash</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span> {
<span class="ident">runners::delete_user</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">id</span>.<span class="ident">forget</span>();
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
} <span class="kw">else</span> {
<span class="prelude-val">Err</span>(<span class="ident">ServiceError::WrongPassword</span>)
}
}
@@ -145,9 +123,7 @@
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">delete_user</span>(<span class="ident">name</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>) -&gt; <span class="ident">ServiceResult</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">name</span>,)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">delete_user</span>(<span class="ident">name</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
}

View File

@@ -73,30 +73,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -113,10 +89,9 @@
* 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">std::borrow::Cow</span>;
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">db_core::UpdateEmail</span>;
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="kw">super</span>::{<span class="ident">AccountCheckPayload</span>, <span class="ident">AccountCheckResp</span>};
@@ -133,20 +108,9 @@
<span class="ident">payload</span>: <span class="ident">web::Json</span><span class="op">&lt;</span><span class="ident">AccountCheckPayload</span><span class="op">&gt;</span>,
<span class="ident">data</span>: <span class="ident">AppData</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</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="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">val</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">exists</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">email_exists</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">val</span>).<span class="kw">await</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="ident">AccountCheckResp</span> { <span class="ident">exists</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="kw">if</span> <span class="ident">x</span> {
<span class="ident">resp</span>.<span class="ident">exists</span> <span class="op">=</span> <span class="bool-val">true</span>;
}
}
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">AccountCheckResp</span> { <span class="ident">exists</span> };
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">resp</span>))
}
@@ -165,25 +129,13 @@
<span class="ident">data</span>.<span class="ident">creds</span>.<span class="ident">email</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">email</span>)<span class="question-mark">?</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;UPDATE mcaptcha_users set email = $1
WHERE name = $2&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">email</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="kw">if</span> <span class="ident">res</span>.<span class="ident">is_err</span>() {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>)) <span class="op">=</span> <span class="ident">res</span> {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>))
<span class="op">&amp;&amp;</span> <span class="ident">err</span>.<span class="ident">message</span>().<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_email_key&quot;</span>)
{
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::EmailTaken</span>);
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>).<span class="ident">into</span>());
}
};
}
<span class="kw">let</span> <span class="ident">update_email</span> <span class="op">=</span> <span class="ident">UpdateEmail</span> {
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">username</span>,
<span class="ident">new_email</span>: <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">email</span>,
};
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">update_email</span>(<span class="kw-2">&amp;</span><span class="ident">update_email</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
}

View File

@@ -195,20 +195,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -228,10 +214,9 @@
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">argon2_creds::Config</span>;
<span class="kw">use</span> <span class="ident">db_core::Login</span>;
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">sqlx::Error::RowNotFound</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::auth::runners::Password</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
@@ -267,15 +252,12 @@
<span class="kw">let</span> <span class="ident">new_hash</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">creds</span>.<span class="ident">password</span>(<span class="kw-2">&amp;</span><span class="ident">update</span>.<span class="ident">new_password</span>)<span class="question-mark">?</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">new_hash</span>,
<span class="kw-2">&amp;</span><span class="ident">user</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">p</span> <span class="op">=</span> <span class="ident">db_core::NameHash</span> {
<span class="ident">username</span>: <span class="ident">user</span>.<span class="ident">to_owned</span>(),
<span class="ident">hash</span>: <span class="ident">new_hash</span>,
};
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">update_password</span>(<span class="kw-2">&amp;</span><span class="ident">p</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
@@ -294,26 +276,15 @@
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">rec</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Password</span>,
<span class="string">r#&quot;SELECT password FROM mcaptcha_users WHERE name = ($1)&quot;#</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="comment">// TODO: verify behavior when account is not found</span>
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">Login::Username</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>)).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">match</span> <span class="ident">rec</span> {
<span class="prelude-val">Ok</span>(<span class="ident">s</span>) =&gt; {
<span class="kw">if</span> <span class="ident">Config::verify</span>(<span class="kw-2">&amp;</span><span class="ident">s</span>.<span class="ident">password</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span> {
<span class="kw">let</span> <span class="ident">update</span>: <span class="ident">UpdatePassword</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</span>().<span class="ident">into</span>();
<span class="ident">update_password_runner</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="ident">update</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
} <span class="kw">else</span> {
<span class="prelude-val">Err</span>(<span class="ident">ServiceError::WrongPassword</span>)
}
}
<span class="prelude-val">Err</span>(<span class="ident">RowNotFound</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::AccountNotFound</span>),
<span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::InternalServerError</span>),
<span class="kw">if</span> <span class="ident">Config::verify</span>(<span class="kw-2">&amp;</span><span class="ident">res</span>.<span class="ident">hash</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span> {
<span class="kw">let</span> <span class="ident">update</span>: <span class="ident">UpdatePassword</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</span>().<span class="ident">into</span>();
<span class="ident">update_password_runner</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="ident">update</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
} <span class="kw">else</span> {
<span class="prelude-val">Err</span>(<span class="ident">ServiceError::WrongPassword</span>)
}
}
@@ -322,28 +293,27 @@
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::ROUTES</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::data::Data</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::tests</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_password_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_password_works</span>() {
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;updatepassuser&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassword2&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;updatepassuser@a.com&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
@@ -355,7 +325,7 @@
<span class="ident">confirm_new_password</span>: <span class="ident">PASSWORD</span>.<span class="ident">into</span>(),
};
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">update_password_runner</span>(<span class="ident">NAME</span>, <span class="ident">update_password</span>.<span class="ident">into</span>(), <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">update_password_runner</span>(<span class="ident">NAME</span>, <span class="ident">update_password</span>.<span class="ident">into</span>(), <span class="ident">data</span>).<span class="kw">await</span>;
<span class="macro">assert!</span>(<span class="ident">res</span>.<span class="ident">is_err</span>());
<span class="macro">assert_eq!</span>(<span class="ident">res</span>, <span class="prelude-val">Err</span>(<span class="ident">ServiceError::PasswordsDontMatch</span>));
@@ -365,7 +335,7 @@
<span class="ident">confirm_new_password</span>: <span class="ident">new_password</span>.<span class="ident">into</span>(),
};
<span class="macro">assert!</span>(<span class="ident">update_password_runner</span>(<span class="ident">NAME</span>, <span class="ident">update_password</span>.<span class="ident">into</span>(), <span class="kw-2">&amp;</span><span class="ident">data</span>)
<span class="macro">assert!</span>(<span class="ident">update_password_runner</span>(<span class="ident">NAME</span>, <span class="ident">update_password</span>.<span class="ident">into</span>(), <span class="ident">data</span>)
.<span class="kw">await</span>
.<span class="ident">is_ok</span>());
@@ -376,6 +346,7 @@
};
<span class="ident">bad_post_req_test</span>(
<span class="ident">data</span>,
<span class="ident">NAME</span>,
<span class="ident">new_password</span>,
<span class="ident">ROUTES</span>.<span class="ident">account</span>.<span class="ident">update_password</span>,
@@ -391,6 +362,7 @@
};
<span class="ident">bad_post_req_test</span>(
<span class="ident">data</span>,
<span class="ident">NAME</span>,
<span class="ident">new_password</span>,
<span class="ident">ROUTES</span>.<span class="ident">account</span>.<span class="ident">update_password</span>,

View File

@@ -66,79 +66,37 @@
<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>
</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">std::borrow::Cow</span>;
* 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">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">db_core::prelude</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::mcaptcha::get_random</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Secret</span> {
<span class="kw">pub</span> <span class="ident">secret</span>: <span class="ident">String</span>,
}
<span class="attribute">#[<span class="ident">my_codegen::get</span>(
<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;crate::V1_API_ROUTES.account.get_secret&quot;</span>,
<span class="ident">wrap</span> <span class="op">=</span> <span class="string">&quot;crate::api::v1::get_middleware()&quot;</span>
)]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_secret</span>(<span class="ident">id</span>: <span class="ident">Identity</span>, <span class="ident">data</span>: <span class="ident">AppData</span>) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</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="kw-2">&amp;</span><span class="ident">username</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">secret</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_secret</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">secret</span>))
}
@@ -156,26 +114,14 @@
<span class="kw">loop</span> {
<span class="ident">secret</span> <span class="op">=</span> <span class="ident">get_random</span>(<span class="number">32</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;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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="kw">if</span> <span class="ident">res</span>.<span class="ident">is_ok</span>() {
<span class="kw">break</span>;
} <span class="kw">else</span> <span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>)) <span class="op">=</span> <span class="ident">res</span> {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>))
<span class="op">&amp;&amp;</span> <span class="ident">err</span>.<span class="ident">message</span>().<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_secret_key&quot;</span>)
{
<span class="kw">continue</span>;
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>).<span class="ident">into</span>());
}
<span class="kw">match</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">update_secret</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">secret</span>).<span class="kw">await</span> {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="kw">break</span>,
<span class="prelude-val">Err</span>(<span class="ident">DBError::SecretTaken</span>) =&gt; <span class="kw">continue</span>,
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
}
}
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
}

View File

@@ -80,39 +80,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -129,8 +96,6 @@
* 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">std::borrow::Cow</span>;
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
@@ -155,22 +120,9 @@
<span class="ident">payload</span>: <span class="kw-2">&amp;</span><span class="ident">AccountCheckPayload</span>,
<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="ident">AccountCheckResp</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="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">val</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">exists</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">username_exists</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">val</span>).<span class="kw">await</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="ident">AccountCheckResp</span> { <span class="ident">exists</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="kw">if</span> <span class="ident">x</span> {
<span class="ident">resp</span>.<span class="ident">exists</span> <span class="op">=</span> <span class="bool-val">true</span>;
}
}
<span class="prelude-val">Ok</span>(<span class="ident">resp</span>)
<span class="prelude-val">Ok</span>(<span class="ident">AccountCheckResp</span> { <span class="ident">exists</span> })
}
}
@@ -193,26 +145,8 @@
<span class="kw">let</span> <span class="ident">processed_uname</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">creds</span>.<span class="ident">username</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">username</span>)<span class="question-mark">?</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;UPDATE mcaptcha_users set name = $1
WHERE name = $2&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">processed_uname</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">update_username</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">processed_uname</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">res</span>.<span class="ident">is_err</span>() {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>)) <span class="op">=</span> <span class="ident">res</span> {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>))
<span class="op">&amp;&amp;</span> <span class="ident">err</span>.<span class="ident">message</span>().<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_name_key&quot;</span>)
{
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::UsernameTaken</span>);
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>).<span class="ident">into</span>());
}
};
}
<span class="ident">id</span>.<span class="ident">forget</span>();
<span class="ident">id</span>.<span class="ident">remember</span>(<span class="ident">processed_uname</span>);

View File

@@ -204,66 +204,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -284,6 +224,7 @@
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web::http::header</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">db_core::errors::DBError</span>;
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::mcaptcha::get_random</span>;
@@ -328,8 +269,6 @@
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">runners</span> {
<span class="kw">use</span> <span class="ident">std::borrow::Cow</span>;
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
@@ -356,7 +295,6 @@
<span class="doccomment">/// returns Ok(()) when everything checks out and the user is authenticated. Erros otherwise</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">login_runner</span>(<span class="ident">payload</span>: <span class="ident">Login</span>, <span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span> {
<span class="kw">use</span> <span class="ident">argon2_creds::Config</span>;
<span class="kw">use</span> <span class="ident">sqlx::Error::RowNotFound</span>;
<span class="kw">let</span> <span class="ident">verify</span> <span class="op">=</span> <span class="op">|</span><span class="ident">stored</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">received</span>: <span class="kw-2">&amp;</span><span class="ident">str</span><span class="op">|</span> {
<span class="kw">if</span> <span class="ident">Config::verify</span>(<span class="ident">stored</span>, <span class="ident">received</span>)<span class="question-mark">?</span> {
@@ -366,55 +304,24 @@
}
};
<span class="kw">if</span> <span class="ident">payload</span>.<span class="ident">login</span>.<span class="ident">contains</span>(<span class="string">&#39;@&#39;</span>) {
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">struct</span> <span class="ident">EmailLogin</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">email_fut</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">EmailLogin</span>,
<span class="string">r#&quot;SELECT name, password FROM mcaptcha_users WHERE email = ($1)&quot;#</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">login</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="kw">match</span> <span class="ident">email_fut</span> {
<span class="prelude-val">Ok</span>(<span class="ident">s</span>) =&gt; {
<span class="ident">verify</span>(<span class="kw-2">&amp;</span><span class="ident">s</span>.<span class="ident">password</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">s</span>.<span class="ident">name</span>)
}
<span class="prelude-val">Err</span>(<span class="ident">RowNotFound</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::AccountNotFound</span>),
<span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::InternalServerError</span>),
}
<span class="kw">let</span> <span class="ident">s</span> <span class="op">=</span> <span class="kw">if</span> <span class="ident">payload</span>.<span class="ident">login</span>.<span class="ident">contains</span>(<span class="string">&#39;@&#39;</span>) {
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">db_core::Login::Email</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">login</span>))
.<span class="kw">await</span><span class="question-mark">?</span>
} <span class="kw">else</span> {
<span class="kw">let</span> <span class="ident">username_fut</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Password</span>,
<span class="string">r#&quot;SELECT password FROM mcaptcha_users WHERE name = ($1)&quot;#</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">login</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">db_core::Login::Username</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">login</span>))
.<span class="kw">await</span><span class="question-mark">?</span>
};
<span class="kw">match</span> <span class="ident">username_fut</span> {
<span class="prelude-val">Ok</span>(<span class="ident">s</span>) =&gt; {
<span class="ident">verify</span>(<span class="kw-2">&amp;</span><span class="ident">s</span>.<span class="ident">password</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">payload</span>.<span class="ident">login</span>)
}
<span class="prelude-val">Err</span>(<span class="ident">RowNotFound</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::AccountNotFound</span>),
<span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::InternalServerError</span>),
}
}
<span class="ident">verify</span>(<span class="kw-2">&amp;</span><span class="ident">s</span>.<span class="ident">hash</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">s</span>.<span class="ident">username</span>)
}
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">register_runner</span>(
<span class="ident">payload</span>: <span class="kw-2">&amp;</span><span class="ident">Register</span>,
<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">if</span> <span class="op">!</span><span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">allow_registration</span> {
<span class="kw">if</span> <span class="op">!</span><span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">allow_registration</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::ClosedForRegistration</span>);
}
@@ -432,48 +339,21 @@
<span class="kw">loop</span> {
<span class="ident">secret</span> <span class="op">=</span> <span class="ident">get_random</span>(<span class="number">32</span>);
<span class="kw">let</span> <span class="ident">res</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">payload</span>.<span class="ident">email</span> {
<span class="ident">res</span> <span class="op">=</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">username</span>,
<span class="kw-2">&amp;</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">secret</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
} <span class="kw">else</span> {
<span class="ident">res</span> <span class="op">=</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">username</span>,
<span class="kw-2">&amp;</span><span class="ident">hash</span>,
<span class="kw-2">&amp;</span><span class="ident">secret</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
}
<span class="kw">if</span> <span class="ident">res</span>.<span class="ident">is_ok</span>() {
<span class="kw">break</span>;
} <span class="kw">else</span> <span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>)) <span class="op">=</span> <span class="ident">res</span> {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>)) {
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">err</span>.<span class="ident">message</span>();
<span class="kw">if</span> <span class="ident">msg</span>.<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_name_key&quot;</span>) {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::UsernameTaken</span>);
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">msg</span>.<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_email_key&quot;</span>) {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::EmailTaken</span>);
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">msg</span>.<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_users_secret_key&quot;</span>) {
<span class="kw">continue</span>;
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::InternalServerError</span>);
}
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>).<span class="ident">into</span>());
}
<span class="kw">let</span> <span class="ident">p</span> <span class="op">=</span> <span class="ident">db_core::Register</span> {
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">username</span>,
<span class="ident">hash</span>: <span class="kw-2">&amp;</span><span class="ident">hash</span>,
<span class="ident">email</span>: <span class="ident">payload</span>.<span class="ident">email</span>.<span class="ident">as_deref</span>(),
<span class="ident">secret</span>: <span class="kw-2">&amp;</span><span class="ident">secret</span>,
};
<span class="kw">match</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">register</span>(<span class="kw-2">&amp;</span><span class="ident">p</span>).<span class="kw">await</span> {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="kw">break</span>,
<span class="prelude-val">Err</span>(<span class="ident">DBError::SecretTaken</span>) =&gt; <span class="kw">continue</span>,
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
}
}
<span class="prelude-val">Ok</span>(())
}
}

View File

@@ -102,60 +102,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -172,13 +118,14 @@
* 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">std::borrow::Cow</span>;
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">libmcaptcha::defense::Level</span>;
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">db_core::errors::DBError</span>;
<span class="kw">use</span> <span class="ident">db_core::CreateCaptcha</span> <span class="kw">as</span> <span class="ident">DBCreateCaptcha</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::get_random</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
@@ -213,11 +160,8 @@
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">runner</span> {
<span class="kw">use</span> <span class="ident">futures::future::try_join_all</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::DefenseBuilder</span>;
<span class="kw">use</span> <span class="ident">log::debug</span>;
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::DefenseBuilder</span>;
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">create</span>(
<span class="ident">payload</span>: <span class="kw-2">&amp;</span><span class="ident">CreateCaptcha</span>,
@@ -231,81 +175,29 @@
<span class="ident">defense</span>.<span class="ident">build</span>()<span class="question-mark">?</span>;
<span class="macro">debug!</span>(<span class="string">&quot;creating config&quot;</span>);
<span class="kw">let</span> <span class="ident">mcaptcha_config</span> <span class="op">=</span>
<span class="comment">// add_mcaptcha_util(payload.duration, &amp;payload.description, &amp;data, username).await?;</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">key</span>;
<span class="kw">let</span> <span class="ident">duration</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">i32</span>;
<span class="kw">loop</span> {
<span class="ident">key</span> <span class="op">=</span> <span class="ident">get_random</span>(<span class="number">32</span>);
<span class="kw">let</span> <span class="ident">p</span> <span class="op">=</span> <span class="ident">DBCreateCaptcha</span> {
<span class="ident">description</span>: <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">description</span>,
<span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">key</span>,
<span class="ident">duration</span>,
};
{
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">key</span>;
<span class="kw">let</span> <span class="ident">resp</span>;
<span class="kw">loop</span> {
<span class="ident">key</span> <span class="op">=</span> <span class="ident">get_random</span>(<span class="number">32</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;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="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>,
<span class="ident">payload</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">description</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="kw">match</span> <span class="ident">res</span> {
<span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>)) =&gt; {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>))
<span class="op">&amp;&amp;</span> <span class="ident">err</span>.<span class="ident">message</span>().<span class="ident">contains</span>(<span class="string">&quot;mcaptcha_config_key_key&quot;</span>)
{
<span class="kw">continue</span>;
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>).<span class="ident">into</span>());
}
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; {
<span class="ident">resp</span> <span class="op">=</span> <span class="ident">MCaptchaDetails</span> {
<span class="ident">key</span>,
<span class="ident">name</span>: <span class="ident">payload</span>.<span class="ident">description</span>.<span class="ident">to_owned</span>(),
};
<span class="kw">break</span>;
<span class="kw">match</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">create_captcha</span>(<span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">p</span>).<span class="kw">await</span> {
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="kw">break</span>,
<span class="prelude-val">Err</span>(<span class="ident">DBError::SecretTaken</span>) =&gt; <span class="kw">continue</span>,
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
}
}
}
<span class="ident">resp</span>
};
<span class="macro">debug!</span>(<span class="string">&quot;config created&quot;</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">payload</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">payload</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">mcaptcha_config</span>.<span class="ident">key</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="ident">data</span>.<span class="ident">db</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="question-mark">?</span>;
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">add_captcha_levels</span>(<span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">levels</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">mcaptcha_config</span> <span class="op">=</span> <span class="ident">MCaptchaDetails</span> {
<span class="ident">name</span>: <span class="ident">payload</span>.<span class="ident">description</span>.<span class="ident">clone</span>(),
<span class="ident">key</span>,
};
<span class="prelude-val">Ok</span>(<span class="ident">mcaptcha_config</span>)
}
}

View File

@@ -61,43 +61,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -119,6 +82,8 @@
<span class="kw">use</span> <span class="ident">libmcaptcha::master::messages::RemoveCaptcha</span>;
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">db_core::Login</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
@@ -138,60 +103,21 @@
<span class="ident">id</span>: <span class="ident">Identity</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">use</span> <span class="ident">argon2_creds::Config</span>;
<span class="kw">use</span> <span class="ident">sqlx::Error::RowNotFound</span>;
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">struct</span> <span class="ident">PasswordID</span> {
<span class="ident">password</span>: <span class="ident">String</span>,
<span class="ident">id</span>: <span class="ident">i32</span>,
<span class="kw">let</span> <span class="ident">hash</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_password</span>(<span class="kw-2">&amp;</span><span class="ident">Login::Username</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>)).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">if</span> <span class="op">!</span><span class="ident">Config::verify</span>(<span class="kw-2">&amp;</span><span class="ident">hash</span>.<span class="ident">hash</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::WrongPassword</span>);
}
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</span>();
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">delete_captcha</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">rec</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">PasswordID</span>,
<span class="string">r#&quot;SELECT ID, password FROM mcaptcha_users WHERE name = ($1)&quot;#</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>;
<span class="kw">match</span> <span class="ident">rec</span> {
<span class="prelude-val">Ok</span>(<span class="ident">rec</span>) =&gt; {
<span class="kw">if</span> <span class="ident">Config::verify</span>(<span class="kw-2">&amp;</span><span class="ident">rec</span>.<span class="ident">password</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">password</span>)<span class="question-mark">?</span> {
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</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 = $2
);&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">rec</span>.<span class="ident">id</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;DELETE FROM mcaptcha_config WHERE key = ($1) AND user_id = $2;&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">rec</span>.<span class="ident">id</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">err</span>) <span class="op">=</span> <span class="ident">data</span>.<span class="ident">captcha</span>.<span class="ident">remove</span>(<span class="ident">RemoveCaptcha</span>(<span class="ident">payload</span>.<span class="ident">key</span>)).<span class="kw">await</span> {
<span class="macro">log::error!</span>(
<span class="string">&quot;Error while trying to remove captcha from cache {}&quot;</span>,
<span class="ident">err</span>
);
}
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
} <span class="kw">else</span> {
<span class="prelude-val">Err</span>(<span class="ident">ServiceError::WrongPassword</span>)
}
}
<span class="prelude-val">Err</span>(<span class="ident">RowNotFound</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::UsernameNotFound</span>),
<span class="prelude-val">Err</span>(<span class="kw">_</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::InternalServerError</span>),
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">err</span>) <span class="op">=</span> <span class="ident">data</span>.<span class="ident">captcha</span>.<span class="ident">remove</span>(<span class="ident">RemoveCaptcha</span>(<span class="ident">payload</span>.<span class="ident">key</span>)).<span class="kw">await</span> {
<span class="macro">log::error!</span>(<span class="string">&quot;Error while trying to remove captcha from cache {}&quot;</span>, <span class="ident">err</span>);
}
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../../../../" data-current-crate="mcaptcha" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>

View File

@@ -391,64 +391,29 @@
<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>
</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>
* 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">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">libmcaptcha</span>::{<span class="ident">defense::Level</span>, <span class="ident">defense::LevelBuilder</span>};
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">db_core::TrafficPattern</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::create</span>::{<span class="ident">runner::create</span> <span class="kw">as</span> <span class="ident">create_runner</span>, <span class="ident">CreateCaptcha</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::update</span>::{<span class="ident">runner::update_captcha</span> <span class="kw">as</span> <span class="ident">update_captcha_runner</span>, <span class="ident">UpdateCaptcha</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
@@ -477,103 +442,96 @@
<span class="ident">cfg</span>.<span class="ident">service</span>(<span class="ident">create</span>);
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Serialize</span>, <span class="ident">Deserialize</span>, <span class="ident">Clone</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">TrafficPattern</span> {
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Default</span>, <span class="ident">Serialize</span>, <span class="ident">Deserialize</span>, <span class="ident">Clone</span>, <span class="ident">Debug</span>)]</span>
<span class="doccomment">/// User&#39;s traffic pattern; used in generating a captcha configuration</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">TrafficPatternRequest</span> {
<span class="doccomment">/// average traffic of user&#39;s website</span>
<span class="kw">pub</span> <span class="ident">avg_traffic</span>: <span class="ident">u32</span>,
<span class="doccomment">/// the peak traffic that the user&#39;s website can handle</span>
<span class="kw">pub</span> <span class="ident">peak_sustainable_traffic</span>: <span class="ident">u32</span>,
<span class="doccomment">/// trafic that bought the user&#39;s website down; optional</span>
<span class="kw">pub</span> <span class="ident">broke_my_site_traffic</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">u32</span><span class="op">&gt;</span>,
<span class="doccomment">/// Captcha description</span>
<span class="kw">pub</span> <span class="ident">description</span>: <span class="ident">String</span>,
}
<span class="kw">impl</span> <span class="ident">TrafficPattern</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">calculate</span>(
<span class="kw-2">&amp;</span><span class="self">self</span>,
<span class="ident">strategy</span>: <span class="kw-2">&amp;</span><span class="ident">DefaultDifficultyStrategy</span>,
) -&gt; <span class="ident">ServiceResult</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">let</span> <span class="kw-2">mut</span> <span class="ident">levels</span> <span class="op">=</span> <span class="macro">vec!</span>[
<span class="ident">LevelBuilder::default</span>()
.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">avg_traffic_difficulty</span>)<span class="question-mark">?</span>
.<span class="ident">visitor_threshold</span>(<span class="self">self</span>.<span class="ident">avg_traffic</span>)
.<span class="ident">build</span>()<span class="question-mark">?</span>,
<span class="ident">LevelBuilder::default</span>()
.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">peak_sustainable_traffic_difficulty</span>)<span class="question-mark">?</span>
.<span class="ident">visitor_threshold</span>(<span class="self">self</span>.<span class="ident">peak_sustainable_traffic</span>)
.<span class="ident">build</span>()<span class="question-mark">?</span>,
];
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">highest_level</span> <span class="op">=</span> <span class="ident">LevelBuilder::default</span>();
<span class="ident">highest_level</span>.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">broke_my_site_traffic_difficulty</span>)<span class="question-mark">?</span>;
<span class="kw">match</span> <span class="self">self</span>.<span class="ident">broke_my_site_traffic</span> {
<span class="prelude-val">Some</span>(<span class="ident">broke_my_site_traffic</span>) =&gt; {
<span class="ident">highest_level</span>.<span class="ident">visitor_threshold</span>(<span class="ident">broke_my_site_traffic</span>)
}
<span class="prelude-val">None</span> =&gt; <span class="kw">match</span> <span class="self">self</span>
.<span class="ident">peak_sustainable_traffic</span>
.<span class="ident">checked_add</span>(<span class="self">self</span>.<span class="ident">peak_sustainable_traffic</span> <span class="op">/</span> <span class="number">2</span>)
{
<span class="prelude-val">Some</span>(<span class="ident">num</span>) =&gt; <span class="ident">highest_level</span>.<span class="ident">visitor_threshold</span>(<span class="ident">num</span>),
<span class="comment">// TODO check for overflow: database saves these values as i32, so this u32 is cast</span>
<span class="comment">// into i32. Should choose bigger number or casts properly</span>
<span class="prelude-val">None</span> =&gt; <span class="ident">highest_level</span>.<span class="ident">visitor_threshold</span>(<span class="ident">u32::MAX</span>),
},
};
<span class="ident">levels</span>.<span class="ident">push</span>(<span class="ident">highest_level</span>.<span class="ident">build</span>()<span class="question-mark">?</span>);
<span class="prelude-val">Ok</span>(<span class="ident">levels</span>)
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="kw-2">&amp;</span><span class="ident">TrafficPatternRequest</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">TrafficPattern</span> {
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">t</span>: <span class="kw-2">&amp;</span><span class="ident">TrafficPatternRequest</span>) -&gt; <span class="self">Self</span> {
<span class="ident">TrafficPattern</span> {
<span class="ident">avg_traffic</span>: <span class="ident">t</span>.<span class="ident">avg_traffic</span>,
<span class="ident">peak_sustainable_traffic</span>: <span class="ident">t</span>.<span class="ident">peak_sustainable_traffic</span>,
<span class="ident">broke_my_site_traffic</span>: <span class="ident">t</span>.<span class="ident">broke_my_site_traffic</span>,
}
}
}
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">calculate</span>(
<span class="ident">tp</span>: <span class="kw-2">&amp;</span><span class="ident">TrafficPattern</span>,
<span class="ident">strategy</span>: <span class="kw-2">&amp;</span><span class="ident">DefaultDifficultyStrategy</span>,
) -&gt; <span class="ident">ServiceResult</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">let</span> <span class="kw-2">mut</span> <span class="ident">levels</span> <span class="op">=</span> <span class="macro">vec!</span>[
<span class="ident">LevelBuilder::default</span>()
.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">avg_traffic_difficulty</span>)<span class="question-mark">?</span>
.<span class="ident">visitor_threshold</span>(<span class="ident">tp</span>.<span class="ident">avg_traffic</span>)
.<span class="ident">build</span>()<span class="question-mark">?</span>,
<span class="ident">LevelBuilder::default</span>()
.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">peak_sustainable_traffic_difficulty</span>)<span class="question-mark">?</span>
.<span class="ident">visitor_threshold</span>(<span class="ident">tp</span>.<span class="ident">peak_sustainable_traffic</span>)
.<span class="ident">build</span>()<span class="question-mark">?</span>,
];
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">highest_level</span> <span class="op">=</span> <span class="ident">LevelBuilder::default</span>();
<span class="ident">highest_level</span>.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">broke_my_site_traffic_difficulty</span>)<span class="question-mark">?</span>;
<span class="kw">match</span> <span class="ident">tp</span>.<span class="ident">broke_my_site_traffic</span> {
<span class="prelude-val">Some</span>(<span class="ident">broke_my_site_traffic</span>) =&gt; {
<span class="ident">highest_level</span>.<span class="ident">visitor_threshold</span>(<span class="ident">broke_my_site_traffic</span>)
}
<span class="prelude-val">None</span> =&gt; <span class="kw">match</span> <span class="ident">tp</span>
.<span class="ident">peak_sustainable_traffic</span>
.<span class="ident">checked_add</span>(<span class="ident">tp</span>.<span class="ident">peak_sustainable_traffic</span> <span class="op">/</span> <span class="number">2</span>)
{
<span class="prelude-val">Some</span>(<span class="ident">num</span>) =&gt; <span class="ident">highest_level</span>.<span class="ident">visitor_threshold</span>(<span class="ident">num</span>),
<span class="comment">// TODO check for overflow: database saves these values as i32, so this u32 is cast</span>
<span class="comment">// into i32. Should choose bigger number or casts properly</span>
<span class="prelude-val">None</span> =&gt; <span class="ident">highest_level</span>.<span class="ident">visitor_threshold</span>(<span class="ident">u32::MAX</span>),
},
};
<span class="ident">levels</span>.<span class="ident">push</span>(<span class="ident">highest_level</span>.<span class="ident">build</span>()<span class="question-mark">?</span>);
<span class="prelude-val">Ok</span>(<span class="ident">levels</span>)
}
<span class="attribute">#[<span class="ident">my_codegen::post</span>(
<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;crate::V1_API_ROUTES.captcha.easy.create&quot;</span>,
<span class="ident">wrap</span> <span class="op">=</span> <span class="string">&quot;crate::api::v1::get_middleware()&quot;</span>
)]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">create</span>(
<span class="ident">payload</span>: <span class="ident">web::Json</span><span class="op">&lt;</span><span class="ident">TrafficPattern</span><span class="op">&gt;</span>,
<span class="ident">payload</span>: <span class="ident">web::Json</span><span class="op">&lt;</span><span class="ident">TrafficPatternRequest</span><span class="op">&gt;</span>,
<span class="ident">data</span>: <span class="ident">AppData</span>,
<span class="ident">id</span>: <span class="ident">Identity</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</span>();
<span class="kw">let</span> <span class="ident">pattern</span> <span class="op">=</span> (<span class="kw-2">&amp;</span><span class="ident">payload</span>).<span class="ident">into</span>();
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span>
<span class="ident">payload</span>.<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>)<span class="question-mark">?</span>;
<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident">pattern</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">CreateCaptcha</span> {
<span class="ident">levels</span>,
<span class="ident">duration</span>: <span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>.<span class="ident">duration</span>,
<span class="ident">duration</span>: <span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>.<span class="ident">duration</span>,
<span class="ident">description</span>: <span class="ident">payload</span>.<span class="ident">description</span>,
};
<span class="kw">let</span> <span class="ident">broke_my_site_traffic</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">broke_my_site_traffic</span>.<span class="ident">map</span>(<span class="op">|</span><span class="ident">n</span><span class="op">|</span> <span class="ident">n</span> <span class="kw">as</span> <span class="ident">i32</span>);
<span class="kw">let</span> <span class="ident">mcaptcha_config</span> <span class="op">=</span> <span class="ident">create_runner</span>(<span class="kw-2">&amp;</span><span class="ident">msg</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="kw">await</span><span class="question-mark">?</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="kw-2">&amp;</span><span class="ident">mcaptcha_config</span>.<span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>,
<span class="ident">payload</span>.<span class="ident">avg_traffic</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="ident">payload</span>.<span class="ident">peak_sustainable_traffic</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="ident">broke_my_site_traffic</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">add_traffic_pattern</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">mcaptcha_config</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">pattern</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">mcaptcha_config</span>))
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Serialize</span>, <span class="ident">Deserialize</span>, <span class="ident">Clone</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">UpdateTrafficPattern</span> {
<span class="kw">pub</span> <span class="ident">pattern</span>: <span class="ident">TrafficPattern</span>,
<span class="kw">pub</span> <span class="ident">pattern</span>: <span class="ident">TrafficPatternRequest</span>,
<span class="kw">pub</span> <span class="ident">key</span>: <span class="ident">String</span>,
}
@@ -588,65 +546,30 @@
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</span>();
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">payload</span>
.<span class="ident">pattern</span>
.<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">pattern</span> <span class="op">=</span> (<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">pattern</span>).<span class="ident">into</span>();
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span>
<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident">pattern</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">UpdateCaptcha</span> {
<span class="ident">levels</span>,
<span class="ident">duration</span>: <span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>.<span class="ident">duration</span>,
<span class="ident">duration</span>: <span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>.<span class="ident">duration</span>,
<span class="ident">description</span>: <span class="ident">payload</span>.<span class="ident">pattern</span>.<span class="ident">description</span>,
<span class="ident">key</span>: <span class="ident">payload</span>.<span class="ident">key</span>,
};
<span class="ident">update_captcha_runner</span>(<span class="kw-2">&amp;</span><span class="ident">msg</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="kw">await</span><span class="question-mark">?</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="kw-2">&amp;</span><span class="ident">msg</span>.<span class="ident">key</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">delete_traffic_pattern</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">msg</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">broke_my_site_traffic</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">pattern</span>.<span class="ident">broke_my_site_traffic</span>.<span class="ident">map</span>(<span class="op">|</span><span class="ident">n</span><span class="op">|</span> <span class="ident">n</span> <span class="kw">as</span> <span class="ident">i32</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="kw-2">&amp;</span><span class="ident">msg</span>.<span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>,
<span class="ident">payload</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">payload</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">broke_my_site_traffic</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">add_traffic_pattern</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">msg</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">pattern</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
<span class="kw">use</span> <span class="ident">actix_web::web::Bytes</span>;
@@ -657,22 +580,22 @@
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::tests</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">isoloated_test</span> {
<span class="kw">use</span> <span class="kw">super</span>::{<span class="ident">LevelBuilder</span>, <span class="ident">TrafficPattern</span>};
<span class="kw">use</span> <span class="kw">super</span>::{<span class="ident">calculate</span>, <span class="ident">LevelBuilder</span>};
<span class="kw">use</span> <span class="ident">db_core::TrafficPattern</span>;
<span class="attribute">#[<span class="ident">test</span>]</span>
<span class="kw">fn</span> <span class="ident">easy_configuration_works</span>() {
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;defaultuserconfgworks&quot;</span>;
<span class="kw">let</span> <span class="ident">settings</span> <span class="op">=</span> <span class="ident"><span class="kw">crate</span>::tests::get_settings</span>();
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">TrafficPattern</span> {
<span class="ident">avg_traffic</span>: <span class="number">100_000</span>,
<span class="ident">peak_sustainable_traffic</span>: <span class="number">1_000_000</span>,
<span class="ident">broke_my_site_traffic</span>: <span class="prelude-val">Some</span>(<span class="number">10_000_000</span>),
<span class="ident">description</span>: <span class="ident">NAME</span>.<span class="ident">into</span>(),
};
<span class="kw">let</span> <span class="ident">strategy</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>;
<span class="kw">let</span> <span class="ident">strategy</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>;
<span class="kw">let</span> <span class="ident">l1</span> <span class="op">=</span> <span class="ident">LevelBuilder::default</span>()
.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">avg_traffic_difficulty</span>)
.<span class="ident">unwrap</span>()
@@ -694,7 +617,7 @@
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="macro">vec!</span>[<span class="ident">l1</span>, <span class="ident">l2</span>, <span class="ident">l3</span>];
<span class="macro">assert_eq!</span>(<span class="ident">payload</span>.<span class="ident">calculate</span>(<span class="ident">strategy</span>).<span class="ident">unwrap</span>(), <span class="ident">levels</span>);
<span class="macro">assert_eq!</span>(<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>, <span class="ident">strategy</span>).<span class="ident">unwrap</span>(), <span class="ident">levels</span>);
<span class="kw">let</span> <span class="ident">estimated_lmax</span> <span class="op">=</span> <span class="ident">LevelBuilder::default</span>()
.<span class="ident">difficulty_factor</span>(<span class="ident">strategy</span>.<span class="ident">broke_my_site_traffic_difficulty</span>)
@@ -704,7 +627,7 @@
.<span class="ident">unwrap</span>();
<span class="ident">payload</span>.<span class="ident">broke_my_site_traffic</span> <span class="op">=</span> <span class="prelude-val">None</span>;
<span class="macro">assert_eq!</span>(
<span class="ident">payload</span>.<span class="ident">calculate</span>(<span class="ident">strategy</span>).<span class="ident">unwrap</span>(),
<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>, <span class="ident">strategy</span>).<span class="ident">unwrap</span>(),
<span class="macro">vec!</span>[<span class="ident">l1</span>, <span class="ident">l2</span>, <span class="ident">estimated_lmax</span>]
);
@@ -726,38 +649,39 @@
<span class="comment">// payload.broke_my_site_traffic = Some(very_large_l2_peak_traffic);</span>
<span class="ident">payload</span>.<span class="ident">peak_sustainable_traffic</span> <span class="op">=</span> <span class="ident">very_large_l2_peak_traffic</span>;
<span class="macro">assert_eq!</span>(
<span class="ident">payload</span>.<span class="ident">calculate</span>(<span class="ident">strategy</span>).<span class="ident">unwrap</span>(),
<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>, <span class="ident">strategy</span>).<span class="ident">unwrap</span>(),
<span class="macro">vec!</span>[<span class="ident">l1</span>, <span class="ident">very_large_l2</span>, <span class="ident">lmax</span>]
);
}
}
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">easy_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">easy_works</span>() {
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;defaultuserconfgworks&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;defaultuserconfgworks@a.com&quot;</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident"><span class="kw">crate</span>::tests::get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span>
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span>
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">TrafficPattern</span> {
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">TrafficPatternRequest</span> {
<span class="ident">avg_traffic</span>: <span class="number">100_000</span>,
<span class="ident">peak_sustainable_traffic</span>: <span class="number">1_000_000</span>,
<span class="ident">broke_my_site_traffic</span>: <span class="prelude-val">Some</span>(<span class="number">10_000_000</span>),
<span class="ident">description</span>: <span class="ident">NAME</span>.<span class="ident">into</span>(),
};
<span class="kw">let</span> <span class="ident">default_levels</span> <span class="op">=</span> <span class="ident">payload</span>
.<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>)
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">default_levels</span> <span class="op">=</span> <span class="ident">calculate</span>(
<span class="kw-2">&amp;</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>).<span class="ident">into</span>(),
<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>,
)
.<span class="ident">unwrap</span>();
<span class="comment">// START create_easy</span>
@@ -785,16 +709,18 @@
<span class="comment">// END create_easy</span>
<span class="comment">// START update_easy</span>
<span class="kw">let</span> <span class="ident">update_pattern</span> <span class="op">=</span> <span class="ident">TrafficPattern</span> {
<span class="kw">let</span> <span class="ident">update_pattern</span> <span class="op">=</span> <span class="ident">TrafficPatternRequest</span> {
<span class="ident">avg_traffic</span>: <span class="number">1_000</span>,
<span class="ident">peak_sustainable_traffic</span>: <span class="number">10_000</span>,
<span class="ident">broke_my_site_traffic</span>: <span class="prelude-val">Some</span>(<span class="number">1_000_000</span>),
<span class="ident">description</span>: <span class="ident">NAME</span>.<span class="ident">into</span>(),
};
<span class="kw">let</span> <span class="ident">updated_default_values</span> <span class="op">=</span> <span class="ident">update_pattern</span>
.<span class="ident">calculate</span>(<span class="kw-2">&amp;</span><span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>)
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">updated_default_values</span> <span class="op">=</span> <span class="ident">calculate</span>(
<span class="kw-2">&amp;</span>(<span class="kw-2">&amp;</span><span class="ident">update_pattern</span>).<span class="ident">into</span>(),
<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">captcha</span>.<span class="ident">default_difficulty_strategy</span>,
)
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">UpdateTrafficPattern</span> {
<span class="ident">pattern</span>: <span class="ident">update_pattern</span>,

View File

@@ -55,30 +55,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -114,7 +90,10 @@
<span class="ident">id</span>: <span class="ident">Identity</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">runner::get_captcha</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">data</span>
.<span class="ident">db</span>
.<span class="ident">get_captcha_levels</span>(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>), <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">levels</span>))
}
@@ -128,33 +107,6 @@
<span class="kw">pub</span> <span class="ident">difficulty_factor</span>: <span class="ident">i32</span>,
<span class="kw">pub</span> <span class="ident">visitor_threshold</span>: <span class="ident">i32</span>,
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">runner</span> {
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="comment">// TODO get metadata from mcaptcha_config table</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_captcha</span>(
<span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">I32Levels</span><span class="op">&gt;</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <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">key</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">levels</span>)
}
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../../../../" data-current-crate="mcaptcha" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

View File

@@ -57,30 +57,27 @@
<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>
</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>
* 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">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats::fetch</span>::{<span class="ident">Stats</span>, <span class="ident">StatsUnixTimestamp</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">routes</span> {
@@ -111,8 +108,7 @@
<span class="ident">id</span>: <span class="ident">Identity</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">stats</span> <span class="op">=</span> <span class="ident">Stats::new</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">stats</span> <span class="op">=</span> <span class="ident">StatsUnixTimestamp::from_stats</span>(<span class="kw-2">&amp;</span><span class="ident">stats</span>);
<span class="kw">let</span> <span class="ident">stats</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">stats</span>.<span class="ident">fetch</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="kw-2">&amp;</span><span class="ident">stats</span>))
}
</code></pre></div>

View File

@@ -210,63 +210,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -283,14 +226,15 @@
* 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">std::borrow::Cow</span>;
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">libmcaptcha::defense::Level</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::master::messages::RenameBuilder</span>;
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">db_core::errors::DBError</span>;
<span class="kw">use</span> <span class="ident">db_core::CreateCaptcha</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::create::MCaptchaDetails</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::get_random</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
@@ -310,16 +254,16 @@
<span class="kw">loop</span> {
<span class="ident">key</span> <span class="op">=</span> <span class="ident">get_random</span>(<span class="number">32</span>);
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">runner::update_key</span>(<span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">if</span> <span class="ident">res</span>.<span class="ident">is_ok</span>() {
<span class="kw">break</span>;
} <span class="kw">else</span> <span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>)) <span class="op">=</span> <span class="ident">res</span> {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>)) {
<span class="kw">continue</span>;
} <span class="kw">else</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">sqlx::Error::Database</span>(<span class="ident">err</span>).<span class="ident">into</span>());
}
};
<span class="kw">match</span> <span class="ident">data</span>
.<span class="ident">db</span>
.<span class="ident">update_captcha_key</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>)
.<span class="kw">await</span>
{
<span class="prelude-val">Ok</span>(<span class="kw">_</span>) =&gt; <span class="kw">break</span>,
<span class="prelude-val">Err</span>(<span class="ident">DBError::SecretTaken</span>) =&gt; <span class="kw">continue</span>,
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
}
}
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</span>();
@@ -361,29 +305,10 @@
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">runner</span> {
<span class="kw">use</span> <span class="ident">futures::future::try_join_all</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha</span>::{<span class="ident">master::messages::RemoveCaptcha</span>, <span class="ident">DefenseBuilder</span>};
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_key</span>(
<span class="ident">key</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">username</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>,
) -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span>(), <span class="ident">sqlx::Error</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="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">old_key</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(())
}
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">update_captcha</span>(
<span class="ident">payload</span>: <span class="kw-2">&amp;</span><span class="ident">UpdateCaptcha</span>,
<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>,
@@ -400,58 +325,21 @@
<span class="comment">// still, needs to be benchmarked</span>
<span class="ident">defense</span>.<span class="ident">build</span>()<span class="question-mark">?</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">payload</span>.<span class="ident">levels</span>.<span class="ident">len</span>() <span class="op">+</span> <span class="number">2</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="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">delete_captcha_levels</span>(<span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">update_fut</span> <span class="op">=</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="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">description</span>,
<span class="ident">payload</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="kw-2">&amp;</span><span class="ident">username</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>); <span class="comment">//.await?;</span>
<span class="kw">let</span> <span class="ident">m</span> <span class="op">=</span> <span class="ident">CreateCaptcha</span> {
<span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>,
<span class="ident">duration</span>: <span class="ident">payload</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">i32</span>,
<span class="ident">description</span>: <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">description</span>,
};
<span class="ident">futs</span>.<span class="ident">push</span>(<span class="ident">update_fut</span>);
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">update_captcha_metadata</span>(<span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">m</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">for</span> <span class="ident">level</span> <span class="kw">in</span> <span class="ident">payload</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">payload</span>.<span class="ident">key</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="ident">data</span>.<span class="ident">db</span>); <span class="comment">//.await?;</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="question-mark">?</span>;
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">add_captcha_levels</span>(<span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">levels</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::CaptchaError</span>(<span class="ident">e</span>)) <span class="op">=</span> <span class="ident">data</span>
.<span class="ident">captcha</span>
.<span class="ident">remove</span>(<span class="ident">RemoveCaptcha</span>(<span class="ident">payload</span>.<span class="ident">key</span>.<span class="ident">clone</span>()))
@@ -483,15 +371,13 @@
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;updateusermcaptcha&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testupdateusermcaptcha@a.com&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="comment">// 1. add mcaptcha token</span>
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;

View File

@@ -146,29 +146,22 @@
<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>
</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>
* 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">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">derive_builder::Builder</span>;
@@ -228,21 +221,13 @@
<span class="doccomment">/// checks all components of the system</span>
<span class="attribute">#[<span class="ident">my_codegen::get</span>(<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;crate::V1_API_ROUTES.meta.health&quot;</span>)]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">health</span>(<span class="ident">data</span>: <span class="ident">AppData</span>) -&gt; <span class="kw">impl</span> <span class="ident">Responder</span> {
<span class="kw">use</span> <span class="ident">sqlx::Connection</span>;
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">resp_builder</span> <span class="op">=</span> <span class="ident">HealthBuilder::default</span>();
<span class="ident">resp_builder</span>.<span class="ident">db</span>(<span class="bool-val">false</span>);
<span class="ident">resp_builder</span>.<span class="ident">redis</span> <span class="op">=</span> <span class="prelude-val">None</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="ident">data</span>.<span class="ident">db</span>.<span class="ident">acquire</span>().<span class="kw">await</span> {
<span class="kw">if</span> <span class="ident">con</span>.<span class="ident">ping</span>().<span class="kw">await</span>.<span class="ident">is_ok</span>() {
<span class="ident">resp_builder</span>.<span class="ident">db</span>(<span class="bool-val">true</span>);
}
};
<span class="ident">resp_builder</span>.<span class="ident">db</span>(<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">ping</span>().<span class="kw">await</span>);
<span class="kw">if</span> <span class="kw">let</span> <span class="ident">SystemGroup::Redis</span>(<span class="kw">_</span>) <span class="op">=</span> <span class="ident">data</span>.<span class="ident">captcha</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="ident">r</span>) <span class="op">=</span> <span class="ident">Redis::new</span>(<span class="ident">RedisConfig::Single</span>(
<span class="ident"><span class="kw">crate</span>::SETTINGS</span>.<span class="ident">redis</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>().<span class="ident">url</span>.<span class="ident">clone</span>(),
<span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">redis</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>().<span class="ident">url</span>.<span class="ident">clone</span>(),
))
.<span class="kw">await</span>
{
@@ -262,7 +247,7 @@
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">http::StatusCode</span>, <span class="ident">test</span>, <span class="ident">App</span>};
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
@@ -284,9 +269,10 @@
}
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">health_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">health_works</span>() {
<span class="macro">println!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">V1_API_ROUTES</span>.<span class="ident">meta</span>.<span class="ident">health</span>);
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident"><span class="kw">crate</span>::tests::get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">test::call_service</span>(

View File

@@ -55,21 +55,21 @@
<span id="50">50</span>
<span id="51">51</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>
* 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">actix_auth_middleware::Authentication</span>;
<span class="kw">use</span> <span class="ident">actix_web::web::ServiceConfig</span>;

View File

@@ -106,25 +106,22 @@
<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>
</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>
* 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">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
@@ -133,8 +130,10 @@
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Serialize</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">AddNotification</span> {
<span class="kw">use</span> <span class="ident">db_core::AddNotification</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">PartialEq</span>, <span class="ident">Default</span>, <span class="ident">Serialize</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">AddNotificationRequest</span> {
<span class="kw">pub</span> <span class="ident">to</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">heading</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">message</span>: <span class="ident">String</span>,
@@ -146,32 +145,27 @@
<span class="ident">wrap</span> <span class="op">=</span> <span class="string">&quot;crate::api::v1::get_middleware()&quot;</span>
)]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">add_notification</span>(
<span class="ident">payload</span>: <span class="ident">web::Json</span><span class="op">&lt;</span><span class="ident">AddNotification</span><span class="op">&gt;</span>,
<span class="ident">payload</span>: <span class="ident">web::Json</span><span class="op">&lt;</span><span class="ident">AddNotificationRequest</span><span class="op">&gt;</span>,
<span class="ident">data</span>: <span class="ident">AppData</span>,
<span class="ident">id</span>: <span class="ident">Identity</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">sender</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="comment">// TODO handle error where payload.to doesnt exist</span>
<span class="macro">sqlx::query!</span>(
<span class="string">&quot;INSERT INTO mcaptcha_notifications (
heading, message, tx, rx)
VALUES (
$1, $2,
(SELECT ID FROM mcaptcha_users WHERE name = $3),
(SELECT ID FROM mcaptcha_users WHERE name = $4)
);&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">heading</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">message</span>,
<span class="kw-2">&amp;</span><span class="ident">sender</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">to</span>,
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">p</span> <span class="op">=</span> <span class="ident">AddNotification</span> {
<span class="ident">from</span>: <span class="kw-2">&amp;</span><span class="ident">sender</span>,
<span class="ident">to</span>: <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">to</span>,
<span class="ident">message</span>: <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">message</span>,
<span class="ident">heading</span>: <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">heading</span>,
};
<span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">create_notification</span>(<span class="kw-2">&amp;</span><span class="ident">p</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
@@ -180,26 +174,26 @@
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">notification_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">notification_works</span>() {
<span class="kw">const</span> <span class="ident">NAME1</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;notifuser1&quot;</span>;
<span class="kw">const</span> <span class="ident">NAME2</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;notiuser2&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL1</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testnotification1@a.com&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL2</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testnotification2@a.com&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME1</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME2</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME1</span>, <span class="ident">EMAIL1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME2</span>, <span class="ident">EMAIL2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">NAME1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>, <span class="ident">EMAIL1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>, <span class="ident">EMAIL2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">AddNotification</span> {
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">AddNotificationRequest</span> {
<span class="ident">to</span>: <span class="ident">NAME2</span>.<span class="ident">into</span>(),
<span class="ident">heading</span>: <span class="string">&quot;Test notification&quot;</span>.<span class="ident">into</span>(),
<span class="ident">message</span>: <span class="string">&quot;Testeing notifications with a dummy message&quot;</span>.<span class="ident">into</span>(),

View File

@@ -147,61 +147,33 @@
<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>
</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>
* 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">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">sqlx::types::time::OffsetDateTime</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">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="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="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="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="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">use</span> <span class="ident">db_core::Notification</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Default</span>, <span class="ident">PartialEq</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">NotificationResp</span> {
<span class="kw">pub</span> <span class="ident">name</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">heading</span>: <span class="ident">String</span>,
@@ -215,13 +187,26 @@
<span class="ident">NotificationResp</span> {
<span class="ident">name</span>: <span class="ident">n</span>.<span class="ident">name</span>.<span class="ident">unwrap</span>(),
<span class="ident">heading</span>: <span class="ident">n</span>.<span class="ident">heading</span>.<span class="ident">unwrap</span>(),
<span class="ident">received</span>: <span class="ident">n</span>.<span class="ident">received</span>.<span class="ident">unwrap</span>().<span class="ident">unix_timestamp</span>(),
<span class="ident">received</span>: <span class="ident">n</span>.<span class="ident">received</span>.<span class="ident">unwrap</span>(),
<span class="ident">id</span>: <span class="ident">n</span>.<span class="ident">id</span>.<span class="ident">unwrap</span>(),
<span class="ident">message</span>: <span class="ident">n</span>.<span class="ident">message</span>.<span class="ident">unwrap</span>(),
}
}
}
<span class="kw">impl</span> <span class="ident">NotificationResp</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">from_notifications</span>(<span class="kw-2">mut</span> <span class="ident">n</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Notification</span><span class="op">&gt;</span>) -&gt; <span class="ident">Vec</span><span class="op">&lt;</span><span class="self">Self</span><span class="op">&gt;</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">n</span>.<span class="ident">len</span>());
<span class="ident">n</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="kw">let</span> <span class="ident">y</span>: <span class="ident">NotificationResp</span> <span class="op">=</span> <span class="ident">x</span>.<span class="ident">into</span>();
<span class="ident">notifications</span>.<span class="ident">push</span>(<span class="ident">y</span>)
});
<span class="ident">notifications</span>
}
}
<span class="doccomment">/// route handler that gets all unread notifications</span>
<span class="attribute">#[<span class="ident">my_codegen::get</span>(
<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;crate::V1_API_ROUTES.notifications.get&quot;</span>,
@@ -234,50 +219,23 @@
<span class="kw">let</span> <span class="ident">receiver</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="comment">// TODO handle error where payload.to doesnt exist</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">runner::get_notification</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">receiver</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">resp</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">NotificationResp</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">notifications</span>
.<span class="ident">drain</span>(<span class="number">0</span>..)
.<span class="ident">map</span>(<span class="op">|</span><span class="ident">x</span><span class="op">|</span> {
<span class="kw">let</span> <span class="ident">y</span>: <span class="ident">NotificationResp</span> <span class="op">=</span> <span class="ident">x</span>.<span class="ident">into</span>();
<span class="ident">y</span>
})
.<span class="ident">collect</span>();
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">resp</span>))
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">runner</span> {
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_notification</span>(
<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>,
<span class="ident">receiver</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">ServiceResult</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="comment">// TODO handle error where payload.to doesnt exist</span>
<span class="kw">let</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="macro">sqlx::query_file_as!</span>(
<span class="ident">Notification</span>,
<span class="string">&quot;src/api/v1/notifications/get_all_unread.sql&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">receiver</span>
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">notifications</span>)
}
<span class="kw">let</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_all_unread_notifications</span>(<span class="kw-2">&amp;</span><span class="ident">receiver</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">NotificationResp::from_notifications</span>(<span class="ident">notifications</span>);
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">notifications</span>))
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::notifications::add::AddNotification</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::notifications::add::AddNotificationRequest</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::tests</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">notification_get_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">notification_get_works</span>() {
<span class="kw">const</span> <span class="ident">NAME1</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;notifuser12&quot;</span>;
<span class="kw">const</span> <span class="ident">NAME2</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;notiuser22&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
@@ -286,21 +244,21 @@
<span class="kw">const</span> <span class="ident">HEADING</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testing notifications get&quot;</span>;
<span class="kw">const</span> <span class="ident">MESSAGE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testing notifications get message&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME1</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME2</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME1</span>, <span class="ident">EMAIL1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME2</span>, <span class="ident">EMAIL2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">NAME1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_data</span>, <span class="ident">_creds2</span>, <span class="ident">signin_resp2</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">NAME2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>, <span class="ident">EMAIL1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>, <span class="ident">EMAIL2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_creds2</span>, <span class="ident">signin_resp2</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">cookies2</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp2</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">AddNotification</span> {
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">AddNotificationRequest</span> {
<span class="ident">to</span>: <span class="ident">NAME2</span>.<span class="ident">into</span>(),
<span class="ident">heading</span>: <span class="ident">HEADING</span>.<span class="ident">into</span>(),
<span class="ident">message</span>: <span class="ident">MESSAGE</span>.<span class="ident">into</span>(),

View File

@@ -145,35 +145,22 @@
<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>
</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>
* 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">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
@@ -187,15 +174,6 @@
<span class="kw">pub</span> <span class="ident">id</span>: <span class="ident">i32</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">NotificationResp</span> {
<span class="kw">pub</span> <span class="ident">name</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">heading</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">message</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">received</span>: <span class="ident">i64</span>,
<span class="kw">pub</span> <span class="ident">id</span>: <span class="ident">i32</span>,
}
<span class="doccomment">/// route handler that marks a notification read</span>
<span class="attribute">#[<span class="ident">my_codegen::post</span>(
<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;crate::V1_API_ROUTES.notifications.mark_read&quot;</span>,
@@ -209,30 +187,27 @@
<span class="kw">let</span> <span class="ident">receiver</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="comment">// TODO handle error where payload.to doesnt exist</span>
<span class="macro">sqlx::query_file_as!</span>(
<span class="ident">Notification</span>,
<span class="string">&quot;src/api/v1/notifications/mark_read.sql&quot;</span>,
<span class="ident">payload</span>.<span class="ident">id</span>,
<span class="kw-2">&amp;</span><span class="ident">receiver</span>
)
.<span class="ident">execute</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="comment">// TODO get payload from path /api/v1/notifications/{id}/read&quot;</span>
<span class="ident">data</span>.<span class="ident">db</span>
.<span class="ident">mark_notification_read</span>(<span class="kw-2">&amp;</span><span class="ident">receiver</span>, <span class="ident">payload</span>.<span class="ident">id</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>())
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::notifications::add::AddNotification</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::notifications::add::AddNotificationRequest</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::notifications::get::NotificationResp</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::tests</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">notification_mark_read_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">notification_mark_read_works</span>() {
<span class="kw">const</span> <span class="ident">NAME1</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;notifuser122&quot;</span>;
<span class="kw">const</span> <span class="ident">NAME2</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;notiuser222&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
@@ -240,22 +215,21 @@
<span class="kw">const</span> <span class="ident">EMAIL2</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testnotification222@a.com&quot;</span>;
<span class="kw">const</span> <span class="ident">HEADING</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testing notifications get&quot;</span>;
<span class="kw">const</span> <span class="ident">MESSAGE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testing notifications get message&quot;</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME1</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME2</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME1</span>, <span class="ident">EMAIL1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME2</span>, <span class="ident">EMAIL2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">NAME1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_data</span>, <span class="ident">_creds2</span>, <span class="ident">signin_resp2</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">NAME2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>, <span class="ident">EMAIL1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>, <span class="ident">EMAIL2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_creds</span>, <span class="ident">signin_resp</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">data</span>, <span class="ident">NAME1</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">_creds2</span>, <span class="ident">signin_resp2</span>) <span class="op">=</span> <span class="ident">signin</span>(<span class="ident">data</span>, <span class="ident">NAME2</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">cookies2</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp2</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">AddNotification</span> {
<span class="kw">let</span> <span class="ident">msg</span> <span class="op">=</span> <span class="ident">AddNotificationRequest</span> {
<span class="ident">to</span>: <span class="ident">NAME2</span>.<span class="ident">into</span>(),
<span class="ident">heading</span>: <span class="ident">HEADING</span>.<span class="ident">into</span>(),
<span class="ident">message</span>: <span class="ident">MESSAGE</span>.<span class="ident">into</span>(),

View File

@@ -49,21 +49,21 @@
<span id="44">44</span>
<span id="45">45</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>
* 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">pub</span> <span class="kw">mod</span> <span class="ident">add</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">get</span>;

View File

@@ -188,28 +188,22 @@
<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>
</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>
* 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="comment">//use actix::prelude::*;</span>
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
@@ -219,9 +213,8 @@
};
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::I32Levels</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats::record::record_fetch</span>;
<span class="comment">//use crate::stats::record::record_fetch;</span>
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::V1_API_ROUTES</span>;
@@ -238,43 +231,58 @@
<span class="ident">payload</span>: <span class="ident">web::Json</span><span class="op">&lt;</span><span class="ident">GetConfigPayload</span><span class="op">&gt;</span>,
<span class="ident">data</span>: <span class="ident">AppData</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</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_config WHERE key = $1)&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">if</span> <span class="ident">res</span>.<span class="ident">exists</span>.<span class="ident">is_none</span>() {
<span class="comment">//if res.exists.is_none() {</span>
<span class="kw">if</span> <span class="op">!</span><span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">captcha_exists</span>(<span class="prelude-val">None</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span> {
<span class="kw">return</span> <span class="prelude-val">Err</span>(<span class="ident">ServiceError::TokenNotFound</span>);
}
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">into_inner</span>();
<span class="kw">match</span> <span class="ident">res</span>.<span class="ident">exists</span> {
<span class="prelude-val">Some</span>(<span class="bool-val">true</span>) =&gt; {
<span class="kw">match</span> <span class="ident">data</span>.<span class="ident">captcha</span>.<span class="ident">get_pow</span>(<span class="ident">payload</span>.<span class="ident">key</span>.<span class="ident">clone</span>()).<span class="kw">await</span> {
<span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(<span class="ident">config</span>)) =&gt; {
<span class="ident">record_fetch</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">config</span>))
}
<span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>) =&gt; {
<span class="ident">init_mcaptcha</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="ident">data</span>
.<span class="ident">captcha</span>
.<span class="ident">get_pow</span>(<span class="ident">payload</span>.<span class="ident">key</span>.<span class="ident">clone</span>())
.<span class="kw">await</span>
.<span class="ident">expect</span>(<span class="string">&quot;mcaptcha should be initialized and ready to go&quot;</span>);
<span class="comment">// background it. would require data::Data to be static</span>
<span class="comment">// to satidfy lifetime</span>
<span class="ident">record_fetch</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">config</span>))
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
}
}
<span class="prelude-val">Some</span>(<span class="bool-val">false</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::TokenNotFound</span>),
<span class="prelude-val">None</span> =&gt; <span class="prelude-val">Err</span>(<span class="ident">ServiceError::TokenNotFound</span>),
<span class="kw">match</span> <span class="ident">data</span>.<span class="ident">captcha</span>.<span class="ident">get_pow</span>(<span class="ident">payload</span>.<span class="ident">key</span>.<span class="ident">clone</span>()).<span class="kw">await</span> {
<span class="prelude-val">Ok</span>(<span class="prelude-val">Some</span>(<span class="ident">config</span>)) =&gt; {
<span class="ident">data</span>.<span class="ident">stats</span>.<span class="ident">record_fetch</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">config</span>))
}
<span class="prelude-val">Ok</span>(<span class="prelude-val">None</span>) =&gt; {
<span class="ident">init_mcaptcha</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="ident">data</span>
.<span class="ident">captcha</span>
.<span class="ident">get_pow</span>(<span class="ident">payload</span>.<span class="ident">key</span>.<span class="ident">clone</span>())
.<span class="kw">await</span>
.<span class="ident">expect</span>(<span class="string">&quot;mcaptcha should be initialized and ready to go&quot;</span>);
<span class="comment">// background it. would require data::Data to be static</span>
<span class="comment">// to satidfy lifetime</span>
<span class="ident">data</span>.<span class="ident">stats</span>.<span class="ident">record_fetch</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">payload</span>.<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">config</span>))
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
}
<span class="comment">// match res.exists {</span>
<span class="comment">// Some(true) =&gt; {</span>
<span class="comment">// match data.captcha.get_pow(payload.key.clone()).await {</span>
<span class="comment">// Ok(Some(config)) =&gt; {</span>
<span class="comment">// record_fetch(&amp;payload.key, &amp;data.db).await;</span>
<span class="comment">// Ok(HttpResponse::Ok().json(config))</span>
<span class="comment">// }</span>
<span class="comment">// Ok(None) =&gt; {</span>
<span class="comment">// init_mcaptcha(&amp;data, &amp;payload.key).await?;</span>
<span class="comment">// let config = data</span>
<span class="comment">// .captcha</span>
<span class="comment">// .get_pow(payload.key.clone())</span>
<span class="comment">// .await</span>
<span class="comment">// .expect(&quot;mcaptcha should be initialized and ready to go&quot;);</span>
<span class="comment">// // background it. would require data::Data to be static</span>
<span class="comment">// // to satidfy lifetime</span>
<span class="comment">// record_fetch(&amp;payload.key, &amp;data.db).await;</span>
<span class="comment">// Ok(HttpResponse::Ok().json(config))</span>
<span class="comment">// }</span>
<span class="comment">// Err(e) =&gt; Err(e.into()),</span>
<span class="comment">// }</span>
<span class="comment">// }</span>
<span class="comment">//</span>
<span class="comment">// Some(false) =&gt; Err(ServiceError::TokenNotFound),</span>
<span class="comment">// None =&gt; Err(ServiceError::TokenNotFound),</span>
<span class="comment">// }</span>
}
<span class="doccomment">/// Call this when [MCaptcha][libmcaptcha::MCaptcha] is not in master.</span>
<span class="doccomment">///</span>
@@ -282,29 +290,8 @@
<span class="doccomment">/// creates [MCaptcha][libmcaptcha::MCaptcha] and adds it to [Master][libmcaptcha::Defense]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">init_mcaptcha</span>(<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>, <span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="comment">// get levels</span>
<span class="kw">let</span> <span class="ident">levels_fut</span> <span class="op">=</span> <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="kw-2">&amp;</span><span class="ident">key</span>,
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>);
<span class="kw">struct</span> <span class="ident">DurationResp</span> {
<span class="ident">duration</span>: <span class="ident">i32</span>,
}
<span class="comment">// get duration</span>
<span class="kw">let</span> <span class="ident">duration_fut</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="kw-2">&amp;</span><span class="ident">key</span>,
)
.<span class="ident">fetch_one</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>);
<span class="comment">//let (levels, duration) = futures::try_join!(levels_fut, duration_fut).await?;</span>
<span class="kw">let</span> (<span class="ident">levels</span>, <span class="ident">duration</span>) <span class="op">=</span> <span class="macro">futures::try_join!</span>(<span class="ident">levels_fut</span>, <span class="ident">duration_fut</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_captcha_levels</span>(<span class="prelude-val">None</span>, <span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">duration</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_captcha_cooldown</span>(<span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="comment">// build defense</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">defense</span> <span class="op">=</span> <span class="ident">DefenseBuilder::default</span>();
@@ -325,7 +312,7 @@
<span class="kw">let</span> <span class="ident">mcaptcha</span> <span class="op">=</span> <span class="ident">MCaptchaBuilder::default</span>()
.<span class="ident">defense</span>(<span class="ident">defense</span>)
<span class="comment">// leaky bucket algorithm&#39;s emission interval</span>
.<span class="ident">duration</span>(<span class="ident">duration</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">u64</span>)
.<span class="ident">duration</span>(<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">u64</span>)
<span class="comment">// .cache(cache)</span>
.<span class="ident">build</span>()
.<span class="ident">unwrap</span>();
@@ -343,11 +330,12 @@
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::pow::PoWConfig</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_pow_config_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_pow_config_works</span>() {
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::tests</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
@@ -357,13 +345,13 @@
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testingpas&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;randomuser@a.com&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">_signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">_signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">get_config_payload</span> <span class="op">=</span> <span class="ident">GetConfigPayload</span> {

View File

@@ -100,21 +100,21 @@
<span id="95">95</span>
<span id="96">96</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>
* 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">actix_web::web</span>;

View File

@@ -136,24 +136,22 @@
<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>
</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>
* 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="doccomment">//! PoW Verification module</span>
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
@@ -161,7 +159,6 @@
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats::record::record_solve</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::V1_API_ROUTES</span>;
@@ -183,13 +180,13 @@
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">key</span> <span class="op">=</span> <span class="ident">payload</span>.<span class="ident">key</span>.<span class="ident">clone</span>();
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">captcha</span>.<span class="ident">verify_pow</span>(<span class="ident">payload</span>.<span class="ident">into_inner</span>()).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="ident">record_solve</span>(<span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span>;
<span class="ident">data</span>.<span class="ident">stats</span>.<span class="ident">record_solve</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">ValidationToken</span> { <span class="ident">token</span>: <span class="ident">res</span> };
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">payload</span>))
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::pow::PoWConfig</span>;
@@ -200,18 +197,17 @@
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">verify_pow_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">verify_pow_works</span>() {
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;powverifyusr&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testingpas&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;verifyuser@a.com&quot;</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">_signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">_signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">get_config_payload</span> <span class="op">=</span> <span class="ident">GetConfigPayload</span> {

View File

@@ -160,24 +160,22 @@
<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>
</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>
* 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="doccomment">//! PoW success token module</span>
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
@@ -185,7 +183,6 @@
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats::record::record_confirm</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::V1_API_ROUTES</span>;
@@ -208,13 +205,13 @@
.<span class="ident">validate_verification_tokens</span>(<span class="ident">payload</span>.<span class="ident">into_inner</span>())
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">payload</span> <span class="op">=</span> <span class="ident">CaptchaValidateResp</span> { <span class="ident">valid</span>: <span class="ident">res</span> };
<span class="ident">record_confirm</span>(<span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span>;
<span class="ident">data</span>.<span class="ident">stats</span>.<span class="ident">record_confirm</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="comment">//println!(&quot;{:?}&quot;, &amp;payload);</span>
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>().<span class="ident">json</span>(<span class="ident">payload</span>))
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::pow::PoWConfig</span>;
@@ -227,7 +224,7 @@
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">validate_captcha_token_works</span>() {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">validate_captcha_token_works</span>() {
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;enterprisetken&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testingpas&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;verifyuser@enter.com&quot;</span>;
@@ -236,13 +233,12 @@
<span class="kw">const</span> <span class="ident">VERIFY_TOKEN_URL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;/api/v1/pow/siteverify&quot;</span>;
<span class="comment">// const UPDATE_URL: &amp;str = &quot;/api/v1/mcaptcha/domain/token/duration/update&quot;;</span>
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">_signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">_signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">get_config_payload</span> <span class="op">=</span> <span class="ident">GetConfigPayload</span> {

View File

@@ -58,21 +58,21 @@
<span id="53">53</span>
<span id="54">54</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>
* 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">actix_auth_middleware::GetLoginRoute</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::account::routes::Account</span>;

View File

@@ -226,6 +226,29 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -247,6 +270,8 @@
<span class="kw">use</span> <span class="ident">actix::prelude</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">argon2_creds</span>::{<span class="ident">Config</span>, <span class="ident">ConfigBuilder</span>, <span class="ident">PasswordPolicy</span>};
<span class="kw">use</span> <span class="ident">db_core::prelude</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident">db_sqlx_postgres</span>::{<span class="ident">ConnectionOptions</span>, <span class="ident">Fresh</span>};
<span class="kw">use</span> <span class="ident">lettre::transport::smtp::authentication::Mechanism</span>;
<span class="kw">use</span> <span class="ident">lettre</span>::{
<span class="ident">transport::smtp::authentication::Credentials</span>, <span class="ident">AsyncSmtpTransport</span>, <span class="ident">Tokio1Executor</span>,
@@ -267,10 +292,12 @@
<span class="ident">system</span>::{<span class="ident">System</span>, <span class="ident">SystemBuilder</span>},
};
<span class="kw">use</span> <span class="ident">sqlx::postgres::PgPoolOptions</span>;
<span class="kw">use</span> <span class="ident">sqlx::PgPool</span>;
<span class="kw">use</span> <span class="ident">db_core::MCDatabase</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors::ServiceResult</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::SETTINGS</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::settings::Settings</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats</span>::{<span class="ident">Dummy</span>, <span class="ident">Real</span>, <span class="ident">Stats</span>};
<span class="macro">macro_rules!</span> <span class="ident">enum_system_actor</span> {
(<span class="macro-nonterminal">$</span><span class="macro-nonterminal">name</span>:<span class="ident">ident</span>, <span class="macro-nonterminal">$</span><span class="kw">type</span>:<span class="macro-nonterminal">ident</span>) =&gt; {
@@ -329,9 +356,13 @@
<span class="comment">// utility function to remove captcha</span>
<span class="macro">enum_system_actor!</span>(<span class="ident">remove</span>, <span class="ident">RemoveCaptcha</span>);
<span class="kw">fn</span> <span class="ident">new_system</span><span class="op">&lt;</span><span class="ident">A</span>: <span class="ident">Save</span>, <span class="ident">B</span>: <span class="ident">MasterTrait</span><span class="op">&gt;</span>(<span class="ident">m</span>: <span class="ident">Addr</span><span class="op">&lt;</span><span class="ident">B</span><span class="op">&gt;</span>, <span class="ident">c</span>: <span class="ident">Addr</span><span class="op">&lt;</span><span class="ident">A</span><span class="op">&gt;</span>) -&gt; <span class="ident">System</span><span class="op">&lt;</span><span class="ident">A</span>, <span class="ident">B</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">new_system</span><span class="op">&lt;</span><span class="ident">A</span>: <span class="ident">Save</span>, <span class="ident">B</span>: <span class="ident">MasterTrait</span><span class="op">&gt;</span>(
<span class="ident">s</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>,
<span class="ident">m</span>: <span class="ident">Addr</span><span class="op">&lt;</span><span class="ident">B</span><span class="op">&gt;</span>,
<span class="ident">c</span>: <span class="ident">Addr</span><span class="op">&lt;</span><span class="ident">A</span><span class="op">&gt;</span>,
) -&gt; <span class="ident">System</span><span class="op">&lt;</span><span class="ident">A</span>, <span class="ident">B</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">pow</span> <span class="op">=</span> <span class="ident">PoWConfigBuilder::default</span>()
.<span class="ident">salt</span>(<span class="ident">SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">salt</span>.<span class="ident">clone</span>())
.<span class="ident">salt</span>(<span class="ident">s</span>.<span class="ident">captcha</span>.<span class="ident">salt</span>.<span class="ident">clone</span>())
.<span class="ident">build</span>()
.<span class="ident">unwrap</span>();
@@ -340,8 +371,8 @@
<span class="comment">// read settings, if Redis is configured then produce a Redis mCaptcha cache</span>
<span class="comment">// based SystemGroup</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">new</span>() -&gt; <span class="self">Self</span> {
<span class="kw">match</span> <span class="kw-2">&amp;</span><span class="ident">SETTINGS</span>.<span class="ident">redis</span> {
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">s</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>) -&gt; <span class="self">Self</span> {
<span class="kw">match</span> <span class="kw-2">&amp;</span><span class="ident">s</span>.<span class="ident">redis</span> {
<span class="prelude-val">Some</span>(<span class="ident">val</span>) =&gt; {
<span class="kw">let</span> <span class="ident">master</span> <span class="op">=</span> <span class="ident">RedisMaster::new</span>(<span class="ident">RedisConfig::Single</span>(<span class="ident">val</span>.<span class="ident">url</span>.<span class="ident">clone</span>()))
.<span class="kw">await</span>
@@ -351,14 +382,14 @@
.<span class="kw">await</span>
.<span class="ident">unwrap</span>()
.<span class="ident">start</span>();
<span class="kw">let</span> <span class="ident">captcha</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::new_system</span>(<span class="ident">master</span>, <span class="ident">cache</span>);
<span class="kw">let</span> <span class="ident">captcha</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::new_system</span>(<span class="ident">s</span>, <span class="ident">master</span>, <span class="ident">cache</span>);
<span class="ident">SystemGroup::Redis</span>(<span class="ident">captcha</span>)
}
<span class="prelude-val">None</span> =&gt; {
<span class="kw">let</span> <span class="ident">master</span> <span class="op">=</span> <span class="ident">EmbeddedMaster::new</span>(<span class="ident">SETTINGS</span>.<span class="ident">captcha</span>.<span class="ident">gc</span>).<span class="ident">start</span>();
<span class="kw">let</span> <span class="ident">master</span> <span class="op">=</span> <span class="ident">EmbeddedMaster::new</span>(<span class="ident">s</span>.<span class="ident">captcha</span>.<span class="ident">gc</span>).<span class="ident">start</span>();
<span class="kw">let</span> <span class="ident">cache</span> <span class="op">=</span> <span class="ident">HashCache::default</span>().<span class="ident">start</span>();
<span class="kw">let</span> <span class="ident">captcha</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::new_system</span>(<span class="ident">master</span>, <span class="ident">cache</span>);
<span class="kw">let</span> <span class="ident">captcha</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::new_system</span>(<span class="ident">s</span>, <span class="ident">master</span>, <span class="ident">cache</span>);
<span class="ident">SystemGroup::Embedded</span>(<span class="ident">captcha</span>)
}
@@ -368,14 +399,18 @@
<span class="doccomment">/// App data</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Data</span> {
<span class="doccomment">/// databse pool</span>
<span class="kw">pub</span> <span class="ident">db</span>: <span class="ident">PgPool</span>,
<span class="doccomment">/// database ops defined by db crates</span>
<span class="kw">pub</span> <span class="ident">db</span>: <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">MCDatabase</span><span class="op">&gt;</span>,
<span class="doccomment">/// credential management configuration</span>
<span class="kw">pub</span> <span class="ident">creds</span>: <span class="ident">Config</span>,
<span class="doccomment">/// mCaptcha system: Redis cache, etc.</span>
<span class="kw">pub</span> <span class="ident">captcha</span>: <span class="ident">SystemGroup</span>,
<span class="doccomment">/// email client</span>
<span class="kw">pub</span> <span class="ident">mailer</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Mailer</span><span class="op">&gt;</span>,
<span class="doccomment">/// app settings</span>
<span class="kw">pub</span> <span class="ident">settings</span>: <span class="ident">Settings</span>,
<span class="doccomment">/// stats recorder</span>
<span class="kw">pub</span> <span class="ident">stats</span>: <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Stats</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span> <span class="ident">Data</span> {
@@ -390,7 +425,7 @@
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="doccomment">/// create new instance of app data</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">new</span>() -&gt; <span class="ident">Arc</span><span class="op">&lt;</span><span class="self">Self</span><span class="op">&gt;</span> {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">s</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>) -&gt; <span class="ident">Arc</span><span class="op">&lt;</span><span class="self">Self</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">creds</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::get_creds</span>();
<span class="kw">let</span> <span class="ident">c</span> <span class="op">=</span> <span class="ident">creds</span>.<span class="ident">clone</span>();
@@ -401,17 +436,28 @@
<span class="macro">log::info!</span>(<span class="string">&quot;Initialized credential manager&quot;</span>);
});
<span class="kw">let</span> <span class="ident">db</span> <span class="op">=</span> <span class="ident">PgPoolOptions::new</span>()
.<span class="ident">max_connections</span>(<span class="ident">SETTINGS</span>.<span class="ident">database</span>.<span class="ident">pool</span>)
.<span class="ident">connect</span>(<span class="kw-2">&amp;</span><span class="ident">SETTINGS</span>.<span class="ident">database</span>.<span class="ident">url</span>)
.<span class="kw">await</span>
.<span class="ident">expect</span>(<span class="string">&quot;Unable to form database pool&quot;</span>);
<span class="kw">let</span> <span class="ident">pool</span> <span class="op">=</span> <span class="ident">s</span>.<span class="ident">database</span>.<span class="ident">pool</span>;
<span class="kw">let</span> <span class="ident">pool_options</span> <span class="op">=</span> <span class="ident">PgPoolOptions::new</span>().<span class="ident">max_connections</span>(<span class="ident">pool</span>);
<span class="kw">let</span> <span class="ident">connection_options</span> <span class="op">=</span> <span class="ident">ConnectionOptions::Fresh</span>(<span class="ident">Fresh</span> {
<span class="ident">pool_options</span>,
<span class="ident">url</span>: <span class="ident">s</span>.<span class="ident">database</span>.<span class="ident">url</span>.<span class="ident">clone</span>(),
});
<span class="kw">let</span> <span class="ident">db</span> <span class="op">=</span> <span class="ident">connection_options</span>.<span class="ident">connect</span>().<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="ident">db</span>.<span class="ident">migrate</span>().<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">stats</span>: <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Stats</span><span class="op">&gt;</span> <span class="op">=</span> <span class="kw">if</span> <span class="ident">s</span>.<span class="ident">captcha</span>.<span class="ident">enable_stats</span> {
<span class="ident">Box::new</span>(<span class="ident">Real::default</span>())
} <span class="kw">else</span> {
<span class="ident">Box::new</span>(<span class="ident">Dummy::default</span>())
};
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data</span> {
<span class="ident">creds</span>,
<span class="ident">db</span>,
<span class="ident">captcha</span>: <span class="ident">SystemGroup::new</span>().<span class="kw">await</span>,
<span class="ident">mailer</span>: <span class="ident"><span class="self">Self</span>::get_mailer</span>(),
<span class="ident">db</span>: <span class="ident">Box::new</span>(<span class="ident">db</span>),
<span class="ident">captcha</span>: <span class="ident">SystemGroup::new</span>(<span class="ident">s</span>).<span class="kw">await</span>,
<span class="ident">mailer</span>: <span class="ident"><span class="self">Self</span>::get_mailer</span>(<span class="ident">s</span>),
<span class="ident">settings</span>: <span class="ident">s</span>.<span class="ident">clone</span>(),
<span class="ident">stats</span>,
};
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">debug_assertions</span>))]</span>
@@ -420,8 +466,8 @@
<span class="ident">Arc::new</span>(<span class="ident">data</span>)
}
<span class="kw">fn</span> <span class="ident">get_mailer</span>() -&gt; <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Mailer</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">smtp</span>) <span class="op">=</span> <span class="ident">SETTINGS</span>.<span class="ident">smtp</span>.<span class="ident">as_ref</span>() {
<span class="kw">fn</span> <span class="ident">get_mailer</span>(<span class="ident">s</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>) -&gt; <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Mailer</span><span class="op">&gt;</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">smtp</span>) <span class="op">=</span> <span class="ident">s</span>.<span class="ident">smtp</span>.<span class="ident">as_ref</span>() {
<span class="kw">let</span> <span class="ident">creds</span> <span class="op">=</span>
<span class="ident">Credentials::new</span>(<span class="ident">smtp</span>.<span class="ident">username</span>.<span class="ident">to_string</span>(), <span class="ident">smtp</span>.<span class="ident">password</span>.<span class="ident">to_string</span>()); <span class="comment">// &quot;smtp_username&quot;.to_string(), &quot;smtp_password&quot;.to_string());</span>

View File

@@ -112,6 +112,12 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -179,6 +185,12 @@
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">date</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">String</span> {
<span class="self">self</span>.<span class="ident">time</span>.<span class="ident">format</span>(<span class="string">&quot;%F %r %z&quot;</span>)
}
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">unix</span>: <span class="ident">i64</span>) -&gt; <span class="self">Self</span> {
<span class="self">Self</span> {
<span class="ident">time</span>: <span class="ident">OffsetDateTime::from_unix_timestamp</span>(<span class="ident">unix</span>),
}
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>

View File

@@ -171,7 +171,6 @@
<span id="166">166</span>
<span id="167">167</span>
<span id="168">168</span>
<span id="169">169</span>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -289,11 +288,10 @@
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">demo_account_works</span>() {
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident"><span class="kw">crate</span>::tests::delete_user</span>(<span class="ident">DEMO_USER</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">AppData::new</span>(<span class="ident">Data::new</span>().<span class="kw">await</span>);
<span class="kw">let</span> <span class="ident">data_inner</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data_inner</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data_inner</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">AppData::new</span>(<span class="ident">data_inner</span>.<span class="ident">clone</span>());
<span class="ident"><span class="kw">crate</span>::tests::delete_user</span>(<span class="ident">data_inner</span>, <span class="ident">DEMO_USER</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">duration</span> <span class="op">=</span> <span class="ident">Duration::from_secs</span>(<span class="ident">DURATION</span>);
<span class="comment">// register works</span>
@@ -302,7 +300,7 @@
<span class="ident">val</span>: <span class="ident">DEMO_USER</span>.<span class="ident">into</span>(),
};
<span class="macro">assert!</span>(<span class="ident">username_exists</span>(<span class="kw-2">&amp;</span><span class="ident">payload</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>().<span class="ident">exists</span>);
<span class="ident">signin</span>(<span class="ident">DEMO_USER</span>, <span class="ident">DEMO_PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">signin</span>(<span class="ident">data_inner</span>, <span class="ident">DEMO_USER</span>, <span class="ident">DEMO_PASSWORD</span>).<span class="kw">await</span>;
<span class="comment">// deletion works</span>
<span class="macro">assert!</span>(<span class="ident">DemoUser::delete_demo_user</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>.<span class="ident">is_ok</span>());
@@ -310,8 +308,8 @@
<span class="comment">// test the runner</span>
<span class="kw">let</span> <span class="ident">user</span> <span class="op">=</span> <span class="ident">DemoUser::spawn</span>(<span class="ident">data</span>, <span class="ident">duration</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> (<span class="ident">data_inner</span>, <span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span>
<span class="ident">add_levels_util</span>(<span class="ident">DEMO_USER</span>, <span class="ident">DEMO_PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span>
<span class="ident">add_levels_util</span>(<span class="ident">data_inner</span>, <span class="ident">DEMO_USER</span>, <span class="ident">DEMO_PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data_inner</span>).<span class="kw">await</span>;

View File

@@ -138,7 +138,6 @@
<span id="133">133</span>
<span id="134">134</span>
<span id="135">135</span>
<span id="136">136</span>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -213,7 +212,6 @@
}
}
<span class="attribute">#[<span class="ident">my_codegen::get</span>(<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;DOCS.assets&quot;</span>)]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">dist</span>(<span class="ident">path</span>: <span class="ident">web::Path</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>) -&gt; <span class="kw">impl</span> <span class="ident">Responder</span> {
<span class="ident">handle_embedded_file</span>(<span class="kw-2">&amp;</span><span class="ident">path</span>)

View File

@@ -22,21 +22,21 @@
<span id="17">17</span>
<span id="18">18</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>
* 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">pub</span> <span class="kw">mod</span> <span class="ident">verification</span>;
</code></pre></div>

View File

@@ -134,21 +134,21 @@
<span id="129">129</span>
<span id="130">130</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>
* 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="doccomment">//! Email operations: verification, notification, etc</span>
<span class="kw">use</span> <span class="ident">lettre</span>::{
<span class="ident">message</span>::{<span class="ident">header</span>, <span class="ident">MultiPart</span>, <span class="ident">SinglePart</span>},
@@ -158,7 +158,6 @@
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::Data</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::SETTINGS</span>;
<span class="kw">const</span> <span class="ident">PAGE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;Login&quot;</span>;
@@ -179,7 +178,7 @@
<span class="ident">to</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
<span class="ident">verification_link</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span>()<span class="op">&gt;</span> {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">smtp</span>) <span class="op">=</span> <span class="ident">SETTINGS</span>.<span class="ident">smtp</span>.<span class="ident">as_ref</span>() {
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Some</span>(<span class="ident">smtp</span>) <span class="op">=</span> <span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">smtp</span>.<span class="ident">as_ref</span>() {
<span class="kw">let</span> <span class="ident">from</span> <span class="op">=</span> <span class="macro">format!</span>(<span class="string">&quot;mCaptcha Admin &lt;{}&gt;&quot;</span>, <span class="ident">smtp</span>.<span class="ident">from</span>);
<span class="kw">let</span> <span class="ident">reply_to</span> <span class="op">=</span> <span class="macro">format!</span>(<span class="string">&quot;mCaptcha Admin &lt;{}&gt;&quot;</span>, <span class="ident">smtp</span>.<span class="ident">reply</span>);
<span class="kw">const</span> <span class="ident">SUBJECT</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;[mCaptcha] Please verify your email&quot;</span>;
@@ -199,7 +198,7 @@ Admin
instance: {}
project website: {}&quot;</span>,
<span class="ident">verification_link</span>,
<span class="ident">SETTINGS</span>.<span class="ident">server</span>.<span class="ident">domain</span>,
<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">settings</span>.<span class="ident">server</span>.<span class="ident">domain</span>,
<span class="ident"><span class="kw">crate</span>::PKG_HOMEPAGE</span>
);
@@ -240,7 +239,8 @@ project website: {}&quot;</span>,
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">email_verification_works</span>() {
<span class="kw">const</span> <span class="ident">TO_ADDR</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;Hello &lt;realaravinth@localhost&gt;&quot;</span>;
<span class="kw">const</span> <span class="ident">VERIFICATION_LINK</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;https://localhost&quot;</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident"><span class="kw">crate</span>::tests::get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">settings</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">settings</span>;
<span class="ident">verification</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="ident">TO_ADDR</span>, <span class="ident">VERIFICATION_LINK</span>)
.<span class="kw">await</span>
.<span class="ident">unwrap</span>();
@@ -253,7 +253,7 @@ project website: {}&quot;</span>,
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">data</span>: <span class="ident">serde_json::Value</span> <span class="op">=</span> <span class="ident">resp</span>.<span class="ident">json</span>().<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>[<span class="number">0</span>];
<span class="kw">let</span> <span class="ident">smtp</span> <span class="op">=</span> <span class="ident">SETTINGS</span>.<span class="ident">smtp</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">smtp</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">smtp</span>.<span class="ident">as_ref</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">from_addr</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>[<span class="string">&quot;headers&quot;</span>][<span class="string">&quot;from&quot;</span>];

View File

@@ -316,22 +316,48 @@
<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>
</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>
* 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">std::convert::From</span>;
@@ -342,6 +368,7 @@
<span class="ident">HttpResponse</span>, <span class="ident">HttpResponseBuilder</span>,
};
<span class="kw">use</span> <span class="ident">argon2_creds::errors::CredsError</span>;
<span class="kw">use</span> <span class="ident">db_core::errors::DBError</span>;
<span class="kw">use</span> <span class="ident">derive_more</span>::{<span class="ident">Display</span>, <span class="ident">Error</span>};
<span class="kw">use</span> <span class="ident">lettre::transport::smtp::Error</span> <span class="kw">as</span> <span class="ident">SmtpError</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::errors::CaptchaError</span>;
@@ -353,6 +380,15 @@
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Display</span>, <span class="ident">Error</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">SmtpErrorWrapper</span>(<span class="ident">SmtpError</span>);
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Display</span>, <span class="ident">Error</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">DBErrorWrapper</span>(<span class="ident">DBError</span>);
<span class="kw">impl</span> <span class="ident">std::cmp::PartialEq</span> <span class="kw">for</span> <span class="ident">DBErrorWrapper</span> {
<span class="kw">fn</span> <span class="ident">eq</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">other</span>: <span class="kw-2">&amp;</span><span class="self">Self</span>) -&gt; <span class="ident">bool</span> {
<span class="macro">format!</span>(<span class="string">&quot;{}&quot;</span>, <span class="self">self</span>.<span class="number">0</span>) <span class="op">==</span> <span class="macro">format!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">other</span>.<span class="number">0</span>)
}
}
<span class="kw">impl</span> <span class="ident">std::cmp::PartialEq</span> <span class="kw">for</span> <span class="ident">SmtpErrorWrapper</span> {
<span class="kw">fn</span> <span class="ident">eq</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">other</span>: <span class="kw-2">&amp;</span><span class="self">Self</span>) -&gt; <span class="ident">bool</span> {
<span class="self">self</span>.<span class="number">0</span>.<span class="ident">status</span>() <span class="op">==</span> <span class="ident">other</span>.<span class="number">0</span>.<span class="ident">status</span>()
@@ -414,13 +450,23 @@
<span class="attribute">#[<span class="ident">display</span>(<span class="ident">fmt</span> <span class="op">=</span> <span class="string">&quot;Unable to send email, contact admin&quot;</span>)]</span>
<span class="ident">UnableToSendEmail</span>(<span class="ident">SmtpErrorWrapper</span>),
<span class="doccomment">/// when the a token name is already taken</span>
<span class="doccomment">/// token not found</span>
<span class="attribute">#[<span class="ident">display</span>(<span class="ident">fmt</span> <span class="op">=</span> <span class="string">&quot;Token not found. Is token registered?&quot;</span>)]</span>
<span class="ident">TokenNotFound</span>,
<span class="attribute">#[<span class="ident">display</span>(<span class="ident">fmt</span> <span class="op">=</span> <span class="string">&quot;{}&quot;</span>, <span class="ident">_0</span>)]</span>
<span class="ident">CaptchaError</span>(<span class="ident">CaptchaError</span>),
<span class="attribute">#[<span class="ident">display</span>(<span class="ident">fmt</span> <span class="op">=</span> <span class="string">&quot;{}&quot;</span>, <span class="ident">_0</span>)]</span>
<span class="ident">DBError</span>(<span class="ident">DBErrorWrapper</span>),
<span class="doccomment">/// captcha not found</span>
<span class="attribute">#[<span class="ident">display</span>(<span class="ident">fmt</span> <span class="op">=</span> <span class="string">&quot;Captcha not found.&quot;</span>)]</span>
<span class="ident">CaptchaNotFound</span>,
<span class="doccomment">/// Traffic pattern not found</span>
<span class="attribute">#[<span class="ident">display</span>(<span class="ident">fmt</span> <span class="op">=</span> <span class="string">&quot;Traffic pattern not found&quot;</span>)]</span>
<span class="ident">TrafficPatternNotFound</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Serialize</span>, <span class="ident">Deserialize</span>)]</span>
@@ -478,6 +524,10 @@
<span class="macro">log::error!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">e</span>.<span class="number">0</span>);
<span class="ident">StatusCode::INTERNAL_SERVER_ERROR</span>
}
<span class="ident">ServiceError::DBError</span>(<span class="kw">_</span>) =&gt; <span class="ident">StatusCode::INTERNAL_SERVER_ERROR</span>,
<span class="ident">ServiceError::CaptchaNotFound</span> =&gt; <span class="ident">StatusCode::NOT_FOUND</span>,
<span class="ident">ServiceError::TrafficPatternNotFound</span> =&gt; <span class="ident">StatusCode::NOT_FOUND</span>,
}
}
}
@@ -497,6 +547,22 @@
}
}
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">DBError</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">ServiceError</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">e</span>: <span class="ident">DBError</span>) -&gt; <span class="ident">ServiceError</span> {
<span class="macro">println!</span>(<span class="string">&quot;from conversin: {}&quot;</span>, <span class="ident">e</span>);
<span class="kw">match</span> <span class="ident">e</span> {
<span class="ident">DBError::UsernameTaken</span> =&gt; <span class="ident">ServiceError::UsernameTaken</span>,
<span class="ident">DBError::SecretTaken</span> =&gt; <span class="ident">ServiceError::InternalServerError</span>,
<span class="ident">DBError::EmailTaken</span> =&gt; <span class="ident">ServiceError::EmailTaken</span>,
<span class="ident">DBError::AccountNotFound</span> =&gt; <span class="ident">ServiceError::AccountNotFound</span>,
<span class="ident">DBError::CaptchaNotFound</span> =&gt; <span class="ident">ServiceError::CaptchaNotFound</span>,
<span class="ident">DBError::TrafficPatternNotFound</span> =&gt; <span class="ident">ServiceError::TrafficPatternNotFound</span>,
<span class="kw">_</span> =&gt; <span class="ident">ServiceError::DBError</span>(<span class="ident">DBErrorWrapper</span>(<span class="ident">e</span>)),
}
}
}
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">ValidationErrors</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">ServiceError</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="kw">_</span>: <span class="ident">ValidationErrors</span>) -&gt; <span class="ident">ServiceError</span> {
@@ -518,21 +584,6 @@
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">sqlx::Error</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">ServiceError</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">e</span>: <span class="ident">sqlx::Error</span>) -&gt; <span class="self">Self</span> {
<span class="kw">use</span> <span class="ident">sqlx::error::Error</span>;
<span class="kw">use</span> <span class="ident">std::borrow::Cow</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="ident">Error::Database</span>(<span class="ident">err</span>) <span class="op">=</span> <span class="ident">e</span> {
<span class="kw">if</span> <span class="ident">err</span>.<span class="ident">code</span>() <span class="op">==</span> <span class="prelude-val">Some</span>(<span class="ident">Cow::from</span>(<span class="string">&quot;23505&quot;</span>)) {
<span class="kw">return</span> <span class="ident">ServiceError::UsernameTaken</span>;
}
}
<span class="ident">ServiceError::InternalServerError</span>
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">SmtpError</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">ServiceError</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
@@ -572,14 +623,6 @@
<span class="ident">ServiceError</span>(<span class="ident">ServiceError</span>),
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">sqlx::Error</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">PageError</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="kw">_</span>: <span class="ident">sqlx::Error</span>) -&gt; <span class="self">Self</span> {
<span class="ident">PageError::InternalServerError</span>
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">ServiceError</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">PageError</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
@@ -588,6 +631,15 @@
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">DBError</span><span class="op">&gt;</span> <span class="kw">for</span> <span class="ident">PageError</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">from</span>(<span class="ident">e</span>: <span class="ident">DBError</span>) -&gt; <span class="self">Self</span> {
<span class="kw">let</span> <span class="ident">se</span>: <span class="ident">ServiceError</span> <span class="op">=</span> <span class="ident">e</span>.<span class="ident">into</span>();
<span class="ident">se</span>.<span class="ident">into</span>()
}
}
<span class="kw">impl</span> <span class="ident">ResponseError</span> <span class="kw">for</span> <span class="ident">PageError</span> {
<span class="kw">fn</span> <span class="ident">error_response</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">HttpResponse</span> {
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::PAGES</span>;

View File

@@ -191,6 +191,10 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -287,7 +291,8 @@
<span class="kw">pub</span> <span class="kw">const</span> <span class="ident">CACHE_AGE</span>: <span class="ident">u32</span> <span class="op">=</span> <span class="number">604800</span>;
<span class="kw">pub</span> <span class="kw">type</span> <span class="ident">AppData</span> <span class="op">=</span> <span class="ident">actix_web::web::Data</span><span class="op">&lt;</span><span class="ident">Arc</span><span class="op">&lt;</span><span class="ident"><span class="kw">crate</span>::data::Data</span><span class="op">&gt;</span><span class="op">&gt;</span>;
<span class="kw">pub</span> <span class="kw">type</span> <span class="ident">ArcData</span> <span class="op">=</span> <span class="ident">Arc</span><span class="op">&lt;</span><span class="ident"><span class="kw">crate</span>::data::Data</span><span class="op">&gt;</span>;
<span class="kw">pub</span> <span class="kw">type</span> <span class="ident">AppData</span> <span class="op">=</span> <span class="ident">actix_web::web::Data</span><span class="op">&lt;</span><span class="ident">ArcData</span><span class="op">&gt;</span>;
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="attribute">#[<span class="ident">actix_web::main</span>]</span>
@@ -302,13 +307,13 @@
<span class="ident">PKG_NAME</span>, <span class="ident">PKG_DESCRIPTION</span>, <span class="ident">PKG_HOMEPAGE</span>, <span class="ident">VERSION</span>, <span class="ident">GIT_COMMIT_HASH</span>
);
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</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="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">settings</span> <span class="op">=</span> <span class="ident">Settings::new</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">actix_web::web::Data::new</span>(<span class="ident">data</span>);
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">demo_user</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">DemoUser</span><span class="op">&gt;</span> <span class="op">=</span> <span class="prelude-val">None</span>;
<span class="kw">if</span> <span class="ident">SETTINGS</span>.<span class="ident">allow_demo</span> <span class="op">&amp;&amp;</span> <span class="ident">SETTINGS</span>.<span class="ident">allow_registration</span> {
<span class="kw">if</span> <span class="ident">settings</span>.<span class="ident">allow_demo</span> <span class="op">&amp;&amp;</span> <span class="ident">settings</span>.<span class="ident">allow_registration</span> {
<span class="ident">demo_user</span> <span class="op">=</span> <span class="prelude-val">Some</span>(
<span class="ident">DemoUser::spawn</span>(<span class="ident">data</span>.<span class="ident">clone</span>(), <span class="ident">Duration::from_secs</span>(<span class="number">60</span> <span class="op">*</span> <span class="number">30</span>))
.<span class="kw">await</span>
@@ -316,16 +321,17 @@
);
}
<span class="macro">println!</span>(<span class="string">&quot;Starting server on: http://{}&quot;</span>, <span class="ident">SETTINGS</span>.<span class="ident">server</span>.<span class="ident">get_ip</span>());
<span class="kw">let</span> <span class="ident">ip</span> <span class="op">=</span> <span class="ident">settings</span>.<span class="ident">server</span>.<span class="ident">get_ip</span>();
<span class="macro">println!</span>(<span class="string">&quot;Starting server on: http://{ip}&quot;</span>);
<span class="ident">HttpServer::new</span>(<span class="kw">move</span> <span class="op">|</span><span class="op">|</span> {
<span class="ident">App::new</span>()
.<span class="ident">wrap</span>(<span class="ident">actix_middleware::Logger::default</span>())
.<span class="ident">wrap</span>(
<span class="ident">actix_middleware::DefaultHeaders::new</span>()
.<span class="ident">header</span>(<span class="string">&quot;Permissions-Policy&quot;</span>, <span class="string">&quot;interest-cohort=()&quot;</span>),
.<span class="ident">add</span>((<span class="string">&quot;Permissions-Policy&quot;</span>, <span class="string">&quot;interest-cohort=()&quot;</span>)),
)
.<span class="ident">wrap</span>(<span class="ident">get_identity_service</span>())
.<span class="ident">wrap</span>(<span class="ident">get_identity_service</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>))
.<span class="ident">wrap</span>(<span class="ident">actix_middleware::Compress::default</span>())
.<span class="ident">app_data</span>(<span class="ident">data</span>.<span class="ident">clone</span>())
.<span class="ident">wrap</span>(<span class="ident">actix_middleware::NormalizePath::new</span>(
@@ -334,7 +340,7 @@
.<span class="ident">configure</span>(<span class="ident">routes::services</span>)
.<span class="ident">app_data</span>(<span class="ident">get_json_err</span>())
})
.<span class="ident">bind</span>(<span class="ident">SETTINGS</span>.<span class="ident">server</span>.<span class="ident">get_ip</span>())
.<span class="ident">bind</span>(<span class="kw-2">&amp;</span><span class="ident">ip</span>)
.<span class="ident">unwrap</span>()
.<span class="ident">run</span>()
.<span class="kw">await</span><span class="question-mark">?</span>;
@@ -354,14 +360,16 @@
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">get_identity_service</span>() -&gt; <span class="ident">IdentityService</span><span class="op">&lt;</span><span class="ident">CookieIdentityPolicy</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">cookie_secret</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">SETTINGS</span>.<span class="ident">server</span>.<span class="ident">cookie_secret</span>;
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">get_identity_service</span>(
<span class="ident">settings</span>: <span class="kw-2">&amp;</span><span class="ident">Settings</span>,
) -&gt; <span class="ident">IdentityService</span><span class="op">&lt;</span><span class="ident">CookieIdentityPolicy</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">cookie_secret</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">server</span>.<span class="ident">cookie_secret</span>;
<span class="ident">IdentityService::new</span>(
<span class="ident">CookieIdentityPolicy::new</span>(<span class="ident">cookie_secret</span>.<span class="ident">as_bytes</span>())
.<span class="ident">name</span>(<span class="string">&quot;Authorization&quot;</span>)
<span class="comment">//TODO change cookie age</span>
.<span class="ident">max_age_secs</span>(<span class="number">216000</span>)
.<span class="ident">domain</span>(<span class="kw-2">&amp;</span><span class="ident">SETTINGS</span>.<span class="ident">server</span>.<span class="ident">domain</span>)
.<span class="ident">domain</span>(<span class="kw-2">&amp;</span><span class="ident">settings</span>.<span class="ident">server</span>.<span class="ident">domain</span>)
.<span class="ident">secure</span>(<span class="bool-val">false</span>),
)
}

View File

@@ -48,30 +48,28 @@
<span id="43">43</span>
<span id="44">44</span>
<span id="45">45</span>
<span id="46">46</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>
* 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">actix_web</span>::{<span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">lazy_static::lazy_static</span>;
<span class="kw">use</span> <span class="ident">my_codegen::get</span>;
<span class="kw">use</span> <span class="ident">sailfish::TemplateOnce</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::RedirectQuery</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::PAGES</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">TemplateOnce</span>)]</span>

View File

@@ -65,21 +65,21 @@
<span id="60">60</span>
<span id="61">61</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>
* 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">pub</span> <span class="kw">mod</span> <span class="ident">login</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">register</span>;

View File

@@ -47,21 +47,21 @@
<span id="42">42</span>
<span id="43">43</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>
* 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">actix_web</span>::{<span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">lazy_static::lazy_static</span>;

View File

@@ -121,20 +121,24 @@
<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>
</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>
* 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">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">lazy_static::lazy_static</span>;

View File

@@ -130,7 +130,8 @@
* 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;.
* 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">actix_auth_middleware::Authentication</span>;
<span class="kw">use</span> <span class="ident">actix_web::web::ServiceConfig</span>;
@@ -170,13 +171,12 @@
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassword&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;templateuser@a.com&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;
@@ -214,7 +214,7 @@
<span class="macro">assert_eq!</span>(<span class="ident">authenticated_resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode::OK</span>);
}
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
}
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>

View File

@@ -100,6 +100,8 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -125,18 +127,19 @@
<span class="kw">mod</span> <span class="ident">settings</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">sitekey</span>;
<span class="kw">use</span> <span class="ident">db_core::Captcha</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors::PageResult</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">use</span> <span class="ident">sitekey::list</span>::{<span class="ident">get_list_sitekeys</span>, <span class="ident">SiteKeys</span>};
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">TemplateOnce</span>, <span class="ident">Clone</span>)]</span>
<span class="attribute">#[<span class="ident">template</span>(<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;panel/index.html&quot;</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">IndexPage</span> {
<span class="ident">sitekeys</span>: <span class="ident">SiteKeys</span>,
<span class="ident">sitekeys</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Captcha</span><span class="op">&gt;</span>,
}
<span class="kw">impl</span> <span class="ident">IndexPage</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">sitekeys</span>: <span class="ident">SiteKeys</span>) -&gt; <span class="self">Self</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">sitekeys</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Captcha</span><span class="op">&gt;</span>) -&gt; <span class="self">Self</span> {
<span class="ident">IndexPage</span> { <span class="ident">sitekeys</span> }
}
}
@@ -148,7 +151,8 @@
<span class="ident">wrap</span> <span class="op">=</span> <span class="string">&quot;crate::pages::get_middleware()&quot;</span>
)]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">panel</span>(<span class="ident">data</span>: <span class="ident">AppData</span>, <span class="ident">id</span>: <span class="ident">Identity</span>) -&gt; <span class="ident">PageResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">sitekeys</span> <span class="op">=</span> <span class="ident">get_list_sitekeys</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">id</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">sitekeys</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_all_user_captchas</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">body</span> <span class="op">=</span> <span class="ident">IndexPage::new</span>(<span class="ident">sitekeys</span>).<span class="ident">render_once</span>().<span class="ident">unwrap</span>();
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>()
.<span class="ident">content_type</span>(<span class="string">&quot;text/html; charset=utf-8&quot;</span>)

View File

@@ -155,7 +155,6 @@
<span class="kw">use</span> <span class="ident">sailfish::TemplateOnce</span>;
<span class="kw">use</span> <span class="ident">sqlx::types::time::OffsetDateTime</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::notifications::get</span>::{<span class="self">self</span>, <span class="ident">runner</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::date::Date</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors::PageResult</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
@@ -181,12 +180,12 @@
<span class="kw">pub</span> <span class="ident">id</span>: <span class="ident">i32</span>,
}
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">get::Notification</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">get::Notification</span>) -&gt; <span class="self">Self</span> {
<span class="kw">impl</span> <span class="ident">From</span><span class="op">&lt;</span><span class="ident">db_core::Notification</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">db_core::Notification</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">unwrap</span>(),
<span class="ident">heading</span>: <span class="ident">n</span>.<span class="ident">heading</span>.<span class="ident">unwrap</span>(),
<span class="ident">received</span>: <span class="ident">n</span>.<span class="ident">received</span>.<span class="ident">unwrap</span>(),
<span class="ident">received</span>: <span class="ident">OffsetDateTime::from_unix_timestamp</span>(<span class="ident">n</span>.<span class="ident">received</span>.<span class="ident">unwrap</span>()),
<span class="ident">id</span>: <span class="ident">n</span>.<span class="ident">id</span>.<span class="ident">unwrap</span>(),
<span class="ident">message</span>: <span class="ident">n</span>.<span class="ident">message</span>.<span class="ident">unwrap</span>(),
}
@@ -209,7 +208,8 @@
<span class="kw">let</span> <span class="ident">receiver</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="comment">// TODO handle error where payload.to doesnt exist</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">runner::get_notification</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">receiver</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="comment">// let mut notifications = runner::get_notification(&amp;data, &amp;receiver).await?;</span>
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_all_unread_notifications</span>(<span class="kw-2">&amp;</span><span class="ident">receiver</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">notifications</span> <span class="op">=</span> <span class="ident">notifications</span>.<span class="ident">drain</span>(<span class="number">0</span>..).<span class="ident">map</span>(<span class="op">|</span><span class="ident">x</span><span class="op">|</span> <span class="ident">x</span>.<span class="ident">into</span>()).<span class="ident">collect</span>();
<span class="kw">let</span> <span class="ident">body</span> <span class="op">=</span> <span class="ident">IndexPage::new</span>(<span class="ident">notifications</span>).<span class="ident">render_once</span>().<span class="ident">unwrap</span>();

View File

@@ -115,15 +115,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -195,22 +186,13 @@
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">settings</span>(<span class="ident">data</span>: <span class="ident">AppData</span>, <span class="ident">id</span>: <span class="ident">Identity</span>) -&gt; <span class="ident">PageResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">struct</span> <span class="ident">DBResult</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="ident">secret</span>: <span class="ident">String</span>,
}
<span class="kw">let</span> <span class="ident">details</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">DBResult</span>,
<span class="string">r#&quot;SELECT email, secret FROM mcaptcha_users WHERE name = ($1)&quot;#</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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">secret</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_secret</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">secret</span> <span class="op">=</span> <span class="ident">secret</span>.<span class="ident">secret</span>;
<span class="kw">let</span> <span class="ident">email</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_email</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">IndexPage</span> {
<span class="ident">email</span>: <span class="ident">details</span>.<span class="ident">email</span>,
<span class="ident">secret</span>: <span class="ident">details</span>.<span class="ident">secret</span>,
<span class="ident">email</span>,
<span class="ident">secret</span>,
<span class="ident">username</span>: <span class="kw-2">&amp;</span><span class="ident">username</span>,
};

View File

@@ -94,21 +94,21 @@
<span id="89">89</span>
<span id="90">90</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>
* 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">actix_web</span>::{<span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">lazy_static::lazy_static</span>;

View File

@@ -42,21 +42,21 @@
<span id="37">37</span>
<span id="38">38</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>
* 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">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">my_codegen::get</span>;

View File

@@ -200,86 +200,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -299,27 +219,17 @@
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">http</span>, <span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">sailfish::TemplateOnce</span>;
<span class="kw">use</span> <span class="ident">sqlx::Error::RowNotFound</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::mcaptcha::easy::TrafficPattern</span>;
<span class="kw">use</span> <span class="ident">db_core::errors::DBError</span>;
<span class="kw">use</span> <span class="ident">db_core::Captcha</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::defense::Level</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::mcaptcha::easy::TrafficPatternRequest</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">const</span> <span class="ident">PAGE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;Edit Sitekey&quot;</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">McaptchaConfig</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="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">Level</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="attribute">#[<span class="ident">derive</span>(<span class="ident">TemplateOnce</span>, <span class="ident">Clone</span>)]</span>
<span class="attribute">#[<span class="ident">template</span>(<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;panel/sitekey/edit/advance.html&quot;</span>)]</span>
<span class="kw">struct</span> <span class="ident">AdvanceEditPage</span> {
@@ -330,10 +240,10 @@
}
<span class="kw">impl</span> <span class="ident">AdvanceEditPage</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">config</span>: <span class="ident">McaptchaConfig</span>, <span class="ident">levels</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Level</span><span class="op">&gt;</span>, <span class="ident">key</span>: <span class="ident">String</span>) -&gt; <span class="self">Self</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">config</span>: <span class="ident">Captcha</span>, <span class="ident">levels</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Level</span><span class="op">&gt;</span>, <span class="ident">key</span>: <span class="ident">String</span>) -&gt; <span class="self">Self</span> {
<span class="ident">AdvanceEditPage</span> {
<span class="ident">duration</span>: <span class="ident">config</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">u32</span>,
<span class="ident">name</span>: <span class="ident">config</span>.<span class="ident">name</span>,
<span class="ident">name</span>: <span class="ident">config</span>.<span class="ident">description</span>,
<span class="ident">levels</span>,
<span class="ident">key</span>,
}
@@ -353,28 +263,8 @@
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">key</span> <span class="op">=</span> <span class="ident">path</span>.<span class="ident">into_inner</span>();
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">McaptchaConfig</span>,
<span class="string">&quot;SELECT config_id, duration, name 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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Level</span>,
<span class="string">&quot;SELECT
difficulty_factor, visitor_threshold
FROM
mcaptcha_levels
WHERE config_id = $1 ORDER BY difficulty_factor ASC&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">config_id</span>
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_captcha_config</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_captcha_levels</span>(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>), <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">body</span> <span class="op">=</span> <span class="ident">AdvanceEditPage::new</span>(<span class="ident">config</span>, <span class="ident">levels</span>, <span class="ident">key</span>)
.<span class="ident">render_once</span>()
@@ -388,12 +278,12 @@
<span class="attribute">#[<span class="ident">template</span>(<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;panel/sitekey/edit/easy/index.html&quot;</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">EasyEditPage</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">pub</span> <span class="ident">form_title</span>: <span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>,
<span class="kw">pub</span> <span class="ident">pattern</span>: <span class="ident">TrafficPattern</span>,
<span class="kw">pub</span> <span class="ident">pattern</span>: <span class="ident">TrafficPatternRequest</span>,
<span class="kw">pub</span> <span class="ident">key</span>: <span class="ident">String</span>,
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">EasyEditPage</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">key</span>: <span class="ident">String</span>, <span class="ident">pattern</span>: <span class="ident">TrafficPattern</span>) -&gt; <span class="self">Self</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">key</span>: <span class="ident">String</span>, <span class="ident">pattern</span>: <span class="ident">TrafficPatternRequest</span>) -&gt; <span class="self">Self</span> {
<span class="self">Self</span> {
<span class="ident">form_title</span>: <span class="ident">PAGE</span>,
<span class="ident">pattern</span>,
@@ -415,65 +305,14 @@
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">key</span> <span class="op">=</span> <span class="ident">path</span>.<span class="ident">into_inner</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">match</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="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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span>
{
<span class="kw">match</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_traffic_pattern</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span> {
<span class="prelude-val">Ok</span>(<span class="ident">c</span>) =&gt; {
<span class="kw">struct</span> <span class="ident">Description</span> {
<span class="ident">name</span>: <span class="ident">String</span>,
}
<span class="kw">let</span> <span class="ident">description</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Description</span>,
<span class="string">&quot;SELECT name FROM mcaptcha_config
WHERE key = $1
AND user_id = (
SELECT user_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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">pattern</span> <span class="op">=</span> <span class="ident">TrafficPattern</span> {
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_captcha_config</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">pattern</span> <span class="op">=</span> <span class="ident">TrafficPatternRequest</span> {
<span class="ident">peak_sustainable_traffic</span>: <span class="ident">c</span>.<span class="ident">peak_sustainable_traffic</span> <span class="kw">as</span> <span class="ident">u32</span>,
<span class="ident">avg_traffic</span>: <span class="ident">c</span>.<span class="ident">avg_traffic</span> <span class="kw">as</span> <span class="ident">u32</span>,
<span class="ident">broke_my_site_traffic</span>: <span class="ident">c</span>.<span class="ident">broke_my_site_traffic</span>.<span class="ident">map</span>(<span class="op">|</span><span class="ident">n</span><span class="op">|</span> <span class="ident">n</span> <span class="kw">as</span> <span class="ident">u32</span>),
<span class="ident">description</span>: <span class="ident">description</span>.<span class="ident">name</span>,
<span class="ident">description</span>: <span class="ident">config</span>.<span class="ident">description</span>,
};
<span class="kw">let</span> <span class="ident">page</span> <span class="op">=</span> <span class="ident">EasyEditPage::new</span>(<span class="ident">key</span>, <span class="ident">pattern</span>).<span class="ident">render_once</span>().<span class="ident">unwrap</span>();
@@ -481,7 +320,7 @@
.<span class="ident">content_type</span>(<span class="string">&quot;text/html; charset=utf-8&quot;</span>)
.<span class="ident">body</span>(<span class="ident">page</span>));
}
<span class="prelude-val">Err</span>(<span class="ident">RowNotFound</span>) =&gt; {
<span class="prelude-val">Err</span>(<span class="ident">DBError::TrafficPatternNotFound</span>) =&gt; {
<span class="kw">return</span> <span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Found</span>()
.<span class="ident">insert_header</span>((
<span class="ident">http::header::LOCATION</span>,
@@ -489,7 +328,10 @@
))
.<span class="ident">finish</span>());
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>()),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; {
<span class="kw">let</span> <span class="ident">e</span>: <span class="ident">ServiceError</span> <span class="op">=</span> <span class="ident">e</span>.<span class="ident">into</span>();
<span class="prelude-val">Err</span>(<span class="ident">e</span>.<span class="ident">into</span>())
}
}
}
@@ -507,14 +349,12 @@
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;editsitekeyuser&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;editsitekeyuser@a.com&quot;</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;

View File

@@ -108,21 +108,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -144,20 +129,21 @@
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">sailfish::TemplateOnce</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::api::v1::mcaptcha::create::MCaptchaDetails</span>;
<span class="kw">use</span> <span class="ident">db_core::Captcha</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">TemplateOnce</span>, <span class="ident">Clone</span>)]</span>
<span class="attribute">#[<span class="ident">template</span>(<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;panel/sitekey/list/index.html&quot;</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">IndexPage</span> {
<span class="ident">sitekeys</span>: <span class="ident">SiteKeys</span>,
<span class="ident">sitekeys</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Captcha</span><span class="op">&gt;</span>,
}
<span class="kw">const</span> <span class="ident">PAGE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;SiteKeys&quot;</span>;
<span class="kw">impl</span> <span class="ident">IndexPage</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">sitekeys</span>: <span class="ident">SiteKeys</span>) -&gt; <span class="self">Self</span> {
<span class="kw">fn</span> <span class="ident">new</span>(<span class="ident">sitekeys</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Captcha</span><span class="op">&gt;</span>) -&gt; <span class="self">Self</span> {
<span class="ident">IndexPage</span> { <span class="ident">sitekeys</span> }
}
}
@@ -168,29 +154,14 @@
<span class="ident">wrap</span> <span class="op">=</span> <span class="string">&quot;crate::pages::get_middleware()&quot;</span>
)]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">list_sitekeys</span>(<span class="ident">data</span>: <span class="ident">AppData</span>, <span class="ident">id</span>: <span class="ident">Identity</span>) -&gt; <span class="ident">PageResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">get_list_sitekeys</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">id</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_all_user_captchas</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">body</span> <span class="op">=</span> <span class="ident">IndexPage::new</span>(<span class="ident">res</span>).<span class="ident">render_once</span>().<span class="ident">unwrap</span>();
<span class="prelude-val">Ok</span>(<span class="ident">HttpResponse::Ok</span>()
.<span class="ident">content_type</span>(<span class="string">&quot;text/html; charset=utf-8&quot;</span>)
.<span class="ident">body</span>(<span class="ident">body</span>))
}
<span class="doccomment">/// utility function to get a list of all sitekeys that a user owns</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">get_list_sitekeys</span>(<span class="ident">data</span>: <span class="kw-2">&amp;</span><span class="ident">AppData</span>, <span class="ident">id</span>: <span class="kw-2">&amp;</span><span class="ident">Identity</span>) -&gt; <span class="ident">PageResult</span><span class="op">&lt;</span><span class="ident">SiteKeys</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</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">MCaptchaDetails</span>,
<span class="string">&quot;SELECT key, name 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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">res</span>)
}
<span class="kw">pub</span> <span class="kw">type</span> <span class="ident">SiteKeys</span> <span class="op">=</span> <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">MCaptchaDetails</span><span class="op">&gt;</span>;
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">test</span> {
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
@@ -206,13 +177,12 @@
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;listsitekeyuser@a.com&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;

View File

@@ -103,21 +103,21 @@
<span id="98">98</span>
<span id="99">99</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>
* 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">mod</span> <span class="ident">add</span>;
<span class="kw">mod</span> <span class="ident">delete</span>;

View File

@@ -133,39 +133,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -185,27 +152,17 @@
<span class="kw">use</span> <span class="ident">actix_identity::Identity</span>;
<span class="kw">use</span> <span class="ident">actix_web</span>::{<span class="ident">web</span>, <span class="ident">HttpResponse</span>, <span class="ident">Responder</span>};
<span class="kw">use</span> <span class="ident">futures</span>::{<span class="ident">future::TryFutureExt</span>, <span class="ident">try_join</span>};
<span class="kw">use</span> <span class="ident">sailfish::TemplateOnce</span>;
<span class="kw">use</span> <span class="ident">db_core::Captcha</span>;
<span class="kw">use</span> <span class="ident">libmcaptcha::defense::Level</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats::fetch::Stats</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats::CaptchaStats</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::AppData</span>;
<span class="kw">const</span> <span class="ident">PAGE</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;SiteKeys&quot;</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">McaptchaConfig</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="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>)]</span>
<span class="kw">struct</span> <span class="ident">Level</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="attribute">#[<span class="ident">derive</span>(<span class="ident">TemplateOnce</span>, <span class="ident">Clone</span>)]</span>
<span class="attribute">#[<span class="ident">template</span>(<span class="ident">path</span> <span class="op">=</span> <span class="string">&quot;panel/sitekey/view/index.html&quot;</span>)]</span>
<span class="kw">struct</span> <span class="ident">IndexPage</span> {
@@ -213,19 +170,19 @@
<span class="ident">name</span>: <span class="ident">String</span>,
<span class="ident">key</span>: <span class="ident">String</span>,
<span class="ident">levels</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Level</span><span class="op">&gt;</span>,
<span class="ident">stats</span>: <span class="ident">Stats</span>,
<span class="ident">stats</span>: <span class="ident">CaptchaStats</span>,
}
<span class="kw">impl</span> <span class="ident">IndexPage</span> {
<span class="kw">fn</span> <span class="ident">new</span>(
<span class="ident">stats</span>: <span class="ident">Stats</span>,
<span class="ident">config</span>: <span class="ident">McaptchaConfig</span>,
<span class="ident">stats</span>: <span class="ident">CaptchaStats</span>,
<span class="ident">config</span>: <span class="ident">Captcha</span>,
<span class="ident">levels</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Level</span><span class="op">&gt;</span>,
<span class="ident">key</span>: <span class="ident">String</span>,
) -&gt; <span class="self">Self</span> {
<span class="ident">IndexPage</span> {
<span class="ident">duration</span>: <span class="ident">config</span>.<span class="ident">duration</span> <span class="kw">as</span> <span class="ident">u32</span>,
<span class="ident">name</span>: <span class="ident">config</span>.<span class="ident">name</span>,
<span class="ident">name</span>: <span class="ident">config</span>.<span class="ident">description</span>,
<span class="ident">levels</span>,
<span class="ident">key</span>,
<span class="ident">stats</span>,
@@ -245,31 +202,9 @@
) -&gt; <span class="ident">PageResult</span><span class="op">&lt;</span><span class="kw">impl</span> <span class="ident">Responder</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">username</span> <span class="op">=</span> <span class="ident">id</span>.<span class="ident">identity</span>().<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">key</span> <span class="op">=</span> <span class="ident">path</span>.<span class="ident">into_inner</span>();
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">McaptchaConfig</span>,
<span class="string">&quot;SELECT config_id, duration, name 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="ident">data</span>.<span class="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">levels_fut</span> <span class="op">=</span> <span class="macro">sqlx::query_as!</span>(
<span class="ident">Level</span>,
<span class="string">&quot;SELECT
difficulty_factor, visitor_threshold
FROM
mcaptcha_levels
WHERE config_id = $1 ORDER BY difficulty_factor ASC&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">config</span>.<span class="ident">config_id</span>
)
.<span class="ident">fetch_all</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
.<span class="ident">err_into</span>();
<span class="kw">let</span> (<span class="ident">stats</span>, <span class="ident">levels</span>) <span class="op">=</span> <span class="macro">try_join!</span>(<span class="ident">Stats::new</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>), <span class="ident">levels_fut</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_captcha_config</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">levels</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">db</span>.<span class="ident">get_captcha_levels</span>(<span class="prelude-val">Some</span>(<span class="kw-2">&amp;</span><span class="ident">username</span>), <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">stats</span> <span class="op">=</span> <span class="ident">data</span>.<span class="ident">stats</span>.<span class="ident">fetch</span>(<span class="kw-2">&amp;</span><span class="ident">data</span>, <span class="kw-2">&amp;</span><span class="ident">username</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>).<span class="kw">await</span><span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">body</span> <span class="op">=</span> <span class="ident">IndexPage::new</span>(<span class="ident">stats</span>, <span class="ident">config</span>, <span class="ident">levels</span>, <span class="ident">key</span>)
.<span class="ident">render_once</span>()
@@ -294,13 +229,12 @@
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;longpassworddomain&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;viewsitekeyuser@a.com&quot;</span>;
{
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
}
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">get_data</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="kw-2">&amp;</span><span class="ident">data</span>;
<span class="ident">delete_user</span>(<span class="ident">data</span>, <span class="ident">NAME</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="ident">data</span>, <span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="ident">signin_resp</span>, <span class="ident">key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">data</span>, <span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">cookies</span> <span class="op">=</span> <span class="macro">get_cookie!</span>(<span class="ident">signin_resp</span>);
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>(<span class="ident">data</span>).<span class="kw">await</span>;

View File

@@ -81,21 +81,21 @@
<span id="76">76</span>
<span id="77">77</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>
* 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">actix_auth_middleware::GetLoginRoute</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">super</span>::auth::routes::Auth</span>;

View File

@@ -244,6 +244,7 @@
<span id="239">239</span>
<span id="240">240</span>
<span id="241">241</span>
<span id="242">242</span>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -282,6 +283,7 @@
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Captcha</span> {
<span class="kw">pub</span> <span class="ident">salt</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">gc</span>: <span class="ident">u64</span>,
<span class="kw">pub</span> <span class="ident">enable_stats</span>: <span class="ident">bool</span>,
<span class="kw">pub</span> <span class="ident">default_difficulty_strategy</span>: <span class="ident">DefaultDifficultyStrategy</span>,
}
@@ -367,10 +369,12 @@
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>() -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="self">Self</span>, <span class="ident">ConfigError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">Config::new</span>();
<span class="kw">const</span> <span class="ident">CURRENT_DIR</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;./config/default.toml&quot;</span>;
<span class="kw">const</span> <span class="ident">ETC</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;/etc/mcaptcha/config.toml&quot;</span>;
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;capatcha.enable_stats&quot;</span>, <span class="bool-val">true</span>.<span class="ident">to_string</span>())
.<span class="ident">expect</span>(<span class="string">&quot;unable to set capatcha.enable_stats default config&quot;</span>);
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="ident">path</span>) <span class="op">=</span> <span class="ident">env::var</span>(<span class="string">&quot;MCAPTCHA_CONFIG&quot;</span>) {
<span class="ident">s</span>.<span class="ident">merge</span>(<span class="ident">File::with_name</span>(<span class="kw-2">&amp;</span><span class="ident">path</span>))<span class="question-mark">?</span>;
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">Path::new</span>(<span class="ident">CURRENT_DIR</span>).<span class="ident">exists</span>() {
@@ -409,8 +413,6 @@
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;database.pool&quot;</span>, <span class="number">2</span>.<span class="ident">to_string</span>())
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t set database pool count&quot;</span>);
<span class="kw">match</span> <span class="ident">s</span>.<span class="ident">try_into</span>() {
<span class="prelude-val">Ok</span>(<span class="ident">val</span>) =&gt; <span class="prelude-val">Ok</span>(<span class="ident">val</span>),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ConfigError::Message</span>(<span class="macro">format!</span>(<span class="string">&quot;\n\nError: {}. If it says missing fields, then please refer to https://github.com/mCaptcha/mcaptcha#configuration to learn more about how mcaptcha reads configuration\n\n&quot;</span>, <span class="ident">e</span>))),

View File

@@ -171,44 +171,6 @@
<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>
</pre><pre class="rust"><code><span class="comment">/*
* Copyright (C) 2022 Aravinth Manivannan &lt;realaravinth@batsense.net&gt;
*
@@ -311,7 +273,6 @@
}
}
<span class="attribute">#[<span class="ident">get</span>(<span class="string">&quot;/assets/{_:.*}&quot;</span>)]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">static_files</span>(<span class="ident">path</span>: <span class="ident">web::Path</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>) -&gt; <span class="kw">impl</span> <span class="ident">Responder</span> {
<span class="ident">handle_assets</span>(<span class="kw-2">&amp;</span><span class="ident">path</span>)
@@ -342,7 +303,6 @@
}
}
<span class="attribute">#[<span class="ident">get</span>(<span class="string">&quot;/{file}&quot;</span>)]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">favicons</span>(<span class="ident">path</span>: <span class="ident">web::Path</span><span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>) -&gt; <span class="kw">impl</span> <span class="ident">Responder</span> {
<span class="macro">debug!</span>(<span class="string">&quot;searching favicons&quot;</span>);
@@ -354,65 +314,29 @@
<span class="kw">use</span> <span class="ident">actix_web::http::StatusCode</span>;
<span class="kw">use</span> <span class="ident">actix_web::test</span>;
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">static_assets_work</span>() {
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">test::call_service</span>(
<span class="kw-2">&amp;</span><span class="ident">app</span>,
<span class="ident">test::TestRequest::get</span>().<span class="ident">uri</span>(<span class="kw-2">*</span><span class="ident"><span class="kw">crate</span>::JS</span>).<span class="ident">to_request</span>(),
)
.<span class="kw">await</span>;
<span class="macro">assert_eq!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode::OK</span>);
<span class="kw">let</span> <span class="ident">urls</span> <span class="op">=</span> [
<span class="kw-2">*</span><span class="ident"><span class="kw">crate</span>::JS</span>,
<span class="kw-2">*</span><span class="ident"><span class="kw">crate</span>::VERIFICATIN_WIDGET_JS</span>,
<span class="kw-2">*</span><span class="ident"><span class="kw">crate</span>::VERIFICATIN_WIDGET_CSS</span>,
<span class="ident"><span class="kw">crate</span>::FILES</span>
.<span class="ident">get</span>(<span class="string">&quot;./static/cache/img/icon-trans.png&quot;</span>)
.<span class="ident">unwrap</span>(),
<span class="string">&quot;/favicon.ico&quot;</span>,
];
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">test::call_service</span>(
<span class="kw-2">&amp;</span><span class="ident">app</span>,
<span class="ident">test::TestRequest::get</span>()
.<span class="ident">uri</span>(<span class="kw-2">*</span><span class="ident"><span class="kw">crate</span>::VERIFICATIN_WIDGET_JS</span>)
.<span class="ident">to_request</span>(),
)
.<span class="kw">await</span>;
<span class="macro">assert_eq!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode::OK</span>);
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">test::call_service</span>(
<span class="kw-2">&amp;</span><span class="ident">app</span>,
<span class="ident">test::TestRequest::get</span>()
.<span class="ident">uri</span>(<span class="kw-2">*</span><span class="ident"><span class="kw">crate</span>::VERIFICATIN_WIDGET_CSS</span>)
.<span class="ident">to_request</span>(),
)
.<span class="kw">await</span>;
<span class="macro">assert_eq!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode::OK</span>);
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">test::call_service</span>(
<span class="kw-2">&amp;</span><span class="ident">app</span>,
<span class="ident">test::TestRequest::get</span>()
.<span class="ident">uri</span>(
<span class="ident"><span class="kw">crate</span>::FILES</span>
.<span class="ident">get</span>(<span class="string">&quot;./static/cache/img/icon-trans.png&quot;</span>)
.<span class="ident">unwrap</span>(),
)
.<span class="ident">to_request</span>(),
)
.<span class="kw">await</span>;
<span class="macro">assert_eq!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode::OK</span>);
}
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">favicons_work</span>() {
<span class="macro">assert!</span>(<span class="ident">Favicons::get</span>(<span class="string">&quot;favicon.ico&quot;</span>).<span class="ident">is_some</span>());
<span class="comment">//let app = test::init_service(App::new().configure(services)).await;</span>
<span class="kw">let</span> <span class="ident">app</span> <span class="op">=</span> <span class="macro">get_app!</span>().<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span> <span class="ident">test::call_service</span>(
<span class="kw-2">&amp;</span><span class="ident">app</span>,
<span class="ident">test::TestRequest::get</span>().<span class="ident">uri</span>(<span class="string">&quot;/favicon.ico&quot;</span>).<span class="ident">to_request</span>(),
)
.<span class="kw">await</span>;
<span class="macro">assert_eq!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode::OK</span>);
<span class="kw">for</span> <span class="ident">u</span> <span class="kw">in</span> <span class="ident">urls</span>.<span class="ident">iter</span>() {
<span class="macro">println!</span>(<span class="string">&quot;[*] Testing static asset at URL: {u}&quot;</span>);
<span class="kw">let</span> <span class="ident">resp</span> <span class="op">=</span>
<span class="ident">test::call_service</span>(<span class="kw-2">&amp;</span><span class="ident">app</span>, <span class="ident">test::TestRequest::get</span>().<span class="ident">uri</span>(<span class="ident">u</span>).<span class="ident">to_request</span>())
.<span class="kw">await</span>;
<span class="macro">assert_eq!</span>(<span class="ident">resp</span>.<span class="ident">status</span>(), <span class="ident">StatusCode::OK</span>);
}
}
}
</code></pre></div>

268
src/mcaptcha/stats.rs.html Normal file
View File

@@ -0,0 +1,268 @@
<!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 `src/stats.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>stats.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="../../mcaptcha/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="../../mcaptcha/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="../../mcaptcha/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>
</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">async_trait::async_trait</span>;
<span class="kw">use</span> <span class="ident">db_core::errors::DBResult</span>;
<span class="kw">use</span> <span class="ident">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::data::Data</span>;
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">Stats</span>: <span class="ident">std::marker::Send</span> <span class="op">+</span> <span class="ident">std::marker::Sync</span> <span class="op">+</span> <span class="ident">CloneStats</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">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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="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">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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="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">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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="doccomment">/// fetch stats</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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">CaptchaStats</span><span class="op">&gt;</span>;
}
<span class="doccomment">/// Trait to clone MCDatabase</span>
<span class="kw">pub</span> <span class="kw">trait</span> <span class="ident">CloneStats</span> {
<span class="doccomment">/// clone DB</span>
<span class="kw">fn</span> <span class="ident">clone_stats</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Stats</span><span class="op">&gt;</span>;
}
<span class="kw">impl</span><span class="op">&lt;</span><span class="ident">T</span><span class="op">&gt;</span> <span class="ident">CloneStats</span> <span class="kw">for</span> <span class="ident">T</span>
<span class="kw">where</span>
<span class="ident">T</span>: <span class="ident">Stats</span> <span class="op">+</span> <span class="ident">Clone</span> <span class="op">+</span> <span class="lifetime">&#39;static</span>,
{
<span class="kw">fn</span> <span class="ident">clone_stats</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">Box</span><span class="op">&lt;</span><span class="kw">dyn</span> <span class="ident">Stats</span><span class="op">&gt;</span> {
<span class="ident">Box::new</span>(<span class="self">self</span>.<span class="ident">clone</span>())
}
}
<span class="comment">//impl Clone for Box&lt;dyn CloneStats&gt; {</span>
<span class="comment">// fn clone(&amp;self) -&gt; Self {</span>
<span class="comment">// Box::clone(self)</span>
<span class="comment">// //(*self).clone_stats()</span>
<span class="comment">// }</span>
<span class="comment">//}</span>
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Default</span>, <span class="ident">PartialEq</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">CaptchaStats</span> {
<span class="kw">pub</span> <span class="ident">config_fetches</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">solves</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">confirms</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Default</span>, <span class="ident">PartialEq</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Real</span>;
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">impl</span> <span class="ident">Stats</span> <span class="kw">for</span> <span class="ident">Real</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">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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="ident">d</span>.<span class="ident">db</span>.<span class="ident">record_fetch</span>(<span class="ident">key</span>).<span class="kw">await</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">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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="ident">d</span>.<span class="ident">db</span>.<span class="ident">record_solve</span>(<span class="ident">key</span>).<span class="kw">await</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">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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="ident">d</span>.<span class="ident">db</span>.<span class="ident">record_confirm</span>(<span class="ident">key</span>).<span class="kw">await</span>
}
<span class="doccomment">/// fetch stats</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">d</span>: <span class="kw-2">&amp;</span><span class="ident">Data</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">CaptchaStats</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">config_fetches_fut</span> <span class="op">=</span> <span class="ident">d</span>.<span class="ident">db</span>.<span class="ident">fetch_config_fetched</span>(<span class="ident">user</span>, <span class="ident">key</span>);
<span class="kw">let</span> <span class="ident">solves_fut</span> <span class="op">=</span> <span class="ident">d</span>.<span class="ident">db</span>.<span class="ident">fetch_solve</span>(<span class="ident">user</span>, <span class="ident">key</span>);
<span class="kw">let</span> <span class="ident">confirms_fut</span> <span class="op">=</span> <span class="ident">d</span>.<span class="ident">db</span>.<span class="ident">fetch_confirm</span>(<span class="ident">user</span>, <span class="ident">key</span>);
<span class="kw">let</span> (<span class="ident">config_fetches</span>, <span class="ident">solves</span>, <span class="ident">confirms</span>) <span class="op">=</span>
<span class="macro">futures::try_join!</span>(<span class="ident">config_fetches_fut</span>, <span class="ident">solves_fut</span>, <span class="ident">confirms_fut</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="ident">CaptchaStats</span> {
<span class="ident">config_fetches</span>,
<span class="ident">solves</span>,
<span class="ident">confirms</span>,
};
<span class="prelude-val">Ok</span>(<span class="ident">res</span>)
}
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Clone</span>, <span class="ident">Default</span>, <span class="ident">PartialEq</span>, <span class="ident">Debug</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Dummy</span>;
<span class="attribute">#[<span class="ident">async_trait</span>]</span>
<span class="kw">impl</span> <span class="ident">Stats</span> <span class="kw">for</span> <span class="ident">Dummy</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="kw">_</span>: <span class="kw-2">&amp;</span><span class="ident">Data</span>, <span class="kw">_</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="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="kw">_</span>: <span class="kw-2">&amp;</span><span class="ident">Data</span>, <span class="kw">_</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="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="kw">_</span>: <span class="kw-2">&amp;</span><span class="ident">Data</span>, <span class="kw">_</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="prelude-val">Ok</span>(())
}
<span class="doccomment">/// fetch stats</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="kw">_</span>: <span class="kw-2">&amp;</span><span class="ident">Data</span>, <span class="kw">_</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="kw">_</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">CaptchaStats</span><span class="op">&gt;</span> {
<span class="prelude-val">Ok</span>(<span class="ident">CaptchaStats::default</span>())
}
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="mcaptcha" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

View File

@@ -1,446 +0,0 @@
<!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 `src/stats/fetch.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>fetch.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="../../../mcaptcha/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="../../../mcaptcha/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="../../../mcaptcha/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>
</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">serde</span>::{<span class="ident">Deserialize</span>, <span class="ident">Serialize</span>};
<span class="kw">use</span> <span class="ident">sqlx::PgPool</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::date::Date</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::errors</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">StatsUnixTimestamp</span> {
<span class="kw">pub</span> <span class="ident">config_fetches</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">solves</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">confirms</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Stats</span> {
<span class="kw">pub</span> <span class="ident">config_fetches</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Date</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">solves</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Date</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">confirms</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Date</span><span class="op">&gt;</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>, <span class="ident">Serialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">StatsPayload</span> {
<span class="kw">pub</span> <span class="ident">key</span>: <span class="ident">String</span>,
}
<span class="kw">impl</span> <span class="ident">Stats</span> {
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">new</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>, <span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">PgPool</span>) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="self">Self</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="ident">config_fetches_fut</span> <span class="op">=</span> <span class="ident">runners::fetch_config_fetched</span>(<span class="ident">user</span>, <span class="ident">key</span>, <span class="ident">db</span>);
<span class="kw">let</span> <span class="ident">solves_fut</span> <span class="op">=</span> <span class="ident">runners::fetch_solve</span>(<span class="ident">user</span>, <span class="ident">key</span>, <span class="ident">db</span>);
<span class="kw">let</span> <span class="ident">confirms_fut</span> <span class="op">=</span> <span class="ident">runners::fetch_confirm</span>(<span class="ident">user</span>, <span class="ident">key</span>, <span class="ident">db</span>);
<span class="kw">let</span> (<span class="ident">config_fetches</span>, <span class="ident">solves</span>, <span class="ident">confirms</span>) <span class="op">=</span>
<span class="macro">futures::try_join!</span>(<span class="ident">config_fetches_fut</span>, <span class="ident">solves_fut</span>, <span class="ident">confirms_fut</span>)<span class="question-mark">?</span>;
<span class="kw">let</span> <span class="ident">res</span> <span class="op">=</span> <span class="self">Self</span> {
<span class="ident">config_fetches</span>,
<span class="ident">solves</span>,
<span class="ident">confirms</span>,
};
<span class="prelude-val">Ok</span>(<span class="ident">res</span>)
}
}
<span class="kw">impl</span> <span class="ident">StatsUnixTimestamp</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">from_stats</span>(<span class="ident">stats</span>: <span class="kw-2">&amp;</span><span class="ident">Stats</span>) -&gt; <span class="self">Self</span> {
<span class="kw">let</span> <span class="ident">config_fetches</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::unix_timestamp</span>(<span class="kw-2">&amp;</span><span class="ident">stats</span>.<span class="ident">config_fetches</span>);
<span class="kw">let</span> <span class="ident">solves</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::unix_timestamp</span>(<span class="kw-2">&amp;</span><span class="ident">stats</span>.<span class="ident">solves</span>);
<span class="kw">let</span> <span class="ident">confirms</span> <span class="op">=</span> <span class="ident"><span class="self">Self</span>::unix_timestamp</span>(<span class="kw-2">&amp;</span><span class="ident">stats</span>.<span class="ident">confirms</span>);
<span class="self">Self</span> {
<span class="ident">config_fetches</span>,
<span class="ident">solves</span>,
<span class="ident">confirms</span>,
}
}
<span class="doccomment">/// featch PoWConfig confirms</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">fn</span> <span class="ident">unix_timestamp</span>(<span class="ident">dates</span>: <span class="kw-2">&amp;</span>[<span class="ident">Date</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">res</span>: <span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">i64</span><span class="op">&gt;</span> <span class="op">=</span> <span class="ident">Vec::with_capacity</span>(<span class="ident">dates</span>.<span class="ident">len</span>());
<span class="ident">dates</span>
.<span class="ident">iter</span>()
.<span class="ident">for_each</span>(<span class="op">|</span><span class="ident">record</span><span class="op">|</span> <span class="ident">res</span>.<span class="ident">push</span>(<span class="ident">record</span>.<span class="ident">time</span>.<span class="ident">unix_timestamp</span>()));
<span class="ident">res</span>
}
}
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">runners</span> {
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="doccomment">/// featch PoWConfig fetches</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch_config_fetched</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>,
<span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">PgPool</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Date</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="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">records</span>)
}
<span class="doccomment">/// featch PoWConfig solves</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch_solve</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>,
<span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">PgPool</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Date</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="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">records</span>)
}
<span class="doccomment">/// featch PoWConfig confirms</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">fetch_confirm</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>,
<span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">PgPool</span>,
) -&gt; <span class="ident">ServiceResult</span><span class="op">&lt;</span><span class="ident">Vec</span><span class="op">&lt;</span><span class="ident">Date</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="ident">db</span>)
.<span class="kw">await</span><span class="question-mark">?</span>;
<span class="prelude-val">Ok</span>(<span class="ident">records</span>)
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="kw">mod</span> <span class="ident">tests</span> {
<span class="kw">use</span> <span class="kw">super</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::stats::record</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="ident"><span class="kw">crate</span>::tests</span>::<span class="kw-2">*</span>;
<span class="kw">use</span> <span class="kw">crate</span>::<span class="kw-2">*</span>;
<span class="attribute">#[<span class="ident">actix_rt::test</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">stats_works</span>() {
<span class="kw">const</span> <span class="ident">NAME</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;statsuser&quot;</span>;
<span class="kw">const</span> <span class="ident">PASSWORD</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;testingpas&quot;</span>;
<span class="kw">const</span> <span class="ident">EMAIL</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;statsuser@a.com&quot;</span>;
<span class="kw">let</span> <span class="ident">data</span> <span class="op">=</span> <span class="ident">Data::new</span>().<span class="kw">await</span>;
<span class="ident">delete_user</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>).<span class="kw">await</span>;
<span class="ident">register_and_signin</span>(<span class="ident">NAME</span>, <span class="ident">EMAIL</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> (<span class="kw">_</span>, <span class="kw">_</span>, <span class="kw">_</span>, <span class="ident">token_key</span>) <span class="op">=</span> <span class="ident">add_levels_util</span>(<span class="ident">NAME</span>, <span class="ident">PASSWORD</span>).<span class="kw">await</span>;
<span class="kw">let</span> <span class="ident">key</span> <span class="op">=</span> <span class="ident">token_key</span>.<span class="ident">key</span>.<span class="ident">clone</span>();
<span class="kw">let</span> <span class="ident">stats</span> <span class="op">=</span> <span class="ident">Stats::new</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">stats</span>.<span class="ident">config_fetches</span>.<span class="ident">len</span>(), <span class="number">0</span>);
<span class="macro">assert_eq!</span>(<span class="ident">stats</span>.<span class="ident">solves</span>.<span class="ident">len</span>(), <span class="number">0</span>);
<span class="macro">assert_eq!</span>(<span class="ident">stats</span>.<span class="ident">confirms</span>.<span class="ident">len</span>(), <span class="number">0</span>);
<span class="macro">futures::join!</span>(
<span class="ident">record_fetch</span>(<span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>),
<span class="ident">record_solve</span>(<span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>),
<span class="ident">record_confirm</span>(<span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>)
);
<span class="kw">let</span> <span class="ident">stats</span> <span class="op">=</span> <span class="ident">Stats::new</span>(<span class="ident">NAME</span>, <span class="kw-2">&amp;</span><span class="ident">key</span>, <span class="kw-2">&amp;</span><span class="ident">data</span>.<span class="ident">db</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
<span class="macro">assert_eq!</span>(<span class="ident">stats</span>.<span class="ident">config_fetches</span>.<span class="ident">len</span>(), <span class="number">1</span>);
<span class="macro">assert_eq!</span>(<span class="ident">stats</span>.<span class="ident">solves</span>.<span class="ident">len</span>(), <span class="number">1</span>);
<span class="macro">assert_eq!</span>(<span class="ident">stats</span>.<span class="ident">confirms</span>.<span class="ident">len</span>(), <span class="number">1</span>);
<span class="kw">let</span> <span class="ident">ustats</span> <span class="op">=</span> <span class="ident">StatsUnixTimestamp::from_stats</span>(<span class="kw-2">&amp;</span><span class="ident">stats</span>);
<span class="macro">assert_eq!</span>(<span class="ident">ustats</span>.<span class="ident">config_fetches</span>.<span class="ident">len</span>(), <span class="number">1</span>);
<span class="macro">assert_eq!</span>(<span class="ident">ustats</span>.<span class="ident">solves</span>.<span class="ident">len</span>(), <span class="number">1</span>);
<span class="macro">assert_eq!</span>(<span class="ident">ustats</span>.<span class="ident">confirms</span>.<span class="ident">len</span>(), <span class="number">1</span>);
}
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../../" data-current-crate="mcaptcha" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

View File

@@ -1,46 +0,0 @@
<!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 `src/stats/mod.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>mod.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="../../../mcaptcha/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="../../../mcaptcha/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="../../../mcaptcha/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>
</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">pub</span> <span class="kw">mod</span> <span class="ident">fetch</span>;
<span class="kw">pub</span> <span class="kw">mod</span> <span class="ident">record</span>;
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../../" data-current-crate="mcaptcha" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

View File

@@ -1,130 +0,0 @@
<!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 `src/stats/record.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>record.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="../../../mcaptcha/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="../../../mcaptcha/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="../../../mcaptcha/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>
</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">sqlx::types::time::OffsetDateTime</span>;
<span class="kw">use</span> <span class="ident">sqlx::PgPool</span>;
<span class="doccomment">/// record PoWConfig fetches</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">record_fetch</span>(<span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">PgPool</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_fetched_stats
(config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1), $2)&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">now</span>,
)
.<span class="ident">execute</span>(<span class="ident">db</span>)
.<span class="kw">await</span>;
}
<span class="doccomment">/// record PoWConfig solves</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">record_solve</span>(<span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">PgPool</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="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">now</span>,
)
.<span class="ident">execute</span>(<span class="ident">db</span>)
.<span class="kw">await</span>;
}
<span class="doccomment">/// record PoWConfig confirms</span>
<span class="attribute">#[<span class="ident">inline</span>]</span>
<span class="kw">pub</span> <span class="kw">async</span> <span class="kw">fn</span> <span class="ident">record_confirm</span>(<span class="ident">key</span>: <span class="kw-2">&amp;</span><span class="ident">str</span>, <span class="ident">db</span>: <span class="kw-2">&amp;</span><span class="ident">PgPool</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_confirmed_stats
(config_id, time) VALUES ((SELECT config_id FROM mcaptcha_config WHERE key = $1), $2)&quot;</span>,
<span class="kw-2">&amp;</span><span class="ident">key</span>,
<span class="kw-2">&amp;</span><span class="ident">now</span>
)
.<span class="ident">execute</span>(<span class="ident">db</span>)
.<span class="kw">await</span>;
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../../" data-current-crate="mcaptcha" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

View File

@@ -1,490 +0,0 @@
<!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 `src/settings.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>settings.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="../../tests_migrate/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="../../tests_migrate/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="../../tests_migrate/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>
</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">std::env</span>;
<span class="kw">use</span> <span class="ident">std::path::Path</span>;
<span class="kw">use</span> <span class="ident">config</span>::{<span class="ident">Config</span>, <span class="ident">ConfigError</span>, <span class="ident">Environment</span>, <span class="ident">File</span>};
<span class="kw">use</span> <span class="ident">log</span>::{<span class="ident">debug</span>, <span class="ident">warn</span>};
<span class="kw">use</span> <span class="ident">serde::Deserialize</span>;
<span class="kw">use</span> <span class="ident">url::Url</span>;
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Server</span> {
<span class="kw">pub</span> <span class="ident">port</span>: <span class="ident">u32</span>,
<span class="kw">pub</span> <span class="ident">domain</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">cookie_secret</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">ip</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">url_prefix</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">pub</span> <span class="ident">proxy_has_tls</span>: <span class="ident">bool</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Captcha</span> {
<span class="kw">pub</span> <span class="ident">salt</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">gc</span>: <span class="ident">u64</span>,
<span class="kw">pub</span> <span class="ident">default_difficulty_strategy</span>: <span class="ident">DefaultDifficultyStrategy</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">DefaultDifficultyStrategy</span> {
<span class="kw">pub</span> <span class="ident">avg_traffic_difficulty</span>: <span class="ident">u32</span>,
<span class="kw">pub</span> <span class="ident">broke_my_site_traffic_difficulty</span>: <span class="ident">u32</span>,
<span class="kw">pub</span> <span class="ident">peak_sustainable_traffic_difficulty</span>: <span class="ident">u32</span>,
<span class="kw">pub</span> <span class="ident">duration</span>: <span class="ident">u32</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Smtp</span> {
<span class="kw">pub</span> <span class="ident">from</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">reply</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">url</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">username</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">password</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">port</span>: <span class="ident">u16</span>,
}
<span class="kw">impl</span> <span class="ident">Server</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">get_ip</span>(<span class="kw-2">&amp;</span><span class="self">self</span>) -&gt; <span class="ident">String</span> {
<span class="macro">format!</span>(<span class="string">&quot;{}:{}&quot;</span>, <span class="self">self</span>.<span class="ident">ip</span>, <span class="self">self</span>.<span class="ident">port</span>)
}
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">struct</span> <span class="ident">DatabaseBuilder</span> {
<span class="kw">pub</span> <span class="ident">port</span>: <span class="ident">u32</span>,
<span class="kw">pub</span> <span class="ident">hostname</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">username</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">password</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">name</span>: <span class="ident">String</span>,
}
<span class="kw">impl</span> <span class="ident">DatabaseBuilder</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">extract_database_url</span>(<span class="ident">url</span>: <span class="kw-2">&amp;</span><span class="ident">Url</span>) -&gt; <span class="self">Self</span> {
<span class="macro">debug!</span>(<span class="string">&quot;Databse name: {}&quot;</span>, <span class="ident">url</span>.<span class="ident">path</span>());
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">path</span> <span class="op">=</span> <span class="ident">url</span>.<span class="ident">path</span>().<span class="ident">split</span>(<span class="string">&#39;/&#39;</span>);
<span class="ident">path</span>.<span class="ident">next</span>();
<span class="kw">let</span> <span class="ident">name</span> <span class="op">=</span> <span class="ident">path</span>.<span class="ident">next</span>().<span class="ident">expect</span>(<span class="string">&quot;no database name&quot;</span>).<span class="ident">to_string</span>();
<span class="ident">DatabaseBuilder</span> {
<span class="ident">port</span>: <span class="ident">url</span>.<span class="ident">port</span>().<span class="ident">expect</span>(<span class="string">&quot;Enter database port&quot;</span>).<span class="ident">into</span>(),
<span class="ident">hostname</span>: <span class="ident">url</span>.<span class="ident">host</span>().<span class="ident">expect</span>(<span class="string">&quot;Enter database host&quot;</span>).<span class="ident">to_string</span>(),
<span class="ident">username</span>: <span class="ident">url</span>.<span class="ident">username</span>().<span class="ident">into</span>(),
<span class="ident">password</span>: <span class="ident">url</span>.<span class="ident">password</span>().<span class="ident">expect</span>(<span class="string">&quot;Enter database password&quot;</span>).<span class="ident">into</span>(),
<span class="ident">name</span>,
}
}
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</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">url</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">pool</span>: <span class="ident">u32</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Redis</span> {
<span class="kw">pub</span> <span class="ident">url</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">pool</span>: <span class="ident">u32</span>,
}
<span class="attribute">#[<span class="ident">derive</span>(<span class="ident">Debug</span>, <span class="ident">Clone</span>, <span class="ident">Deserialize</span>)]</span>
<span class="kw">pub</span> <span class="kw">struct</span> <span class="ident">Settings</span> {
<span class="kw">pub</span> <span class="ident">debug</span>: <span class="ident">bool</span>,
<span class="kw">pub</span> <span class="ident">commercial</span>: <span class="ident">bool</span>,
<span class="kw">pub</span> <span class="ident">database</span>: <span class="ident">Database</span>,
<span class="kw">pub</span> <span class="ident">redis</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Redis</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">server</span>: <span class="ident">Server</span>,
<span class="kw">pub</span> <span class="ident">captcha</span>: <span class="ident">Captcha</span>,
<span class="kw">pub</span> <span class="ident">source_code</span>: <span class="ident">String</span>,
<span class="kw">pub</span> <span class="ident">smtp</span>: <span class="prelude-ty">Option</span><span class="op">&lt;</span><span class="ident">Smtp</span><span class="op">&gt;</span>,
<span class="kw">pub</span> <span class="ident">allow_registration</span>: <span class="ident">bool</span>,
<span class="kw">pub</span> <span class="ident">allow_demo</span>: <span class="ident">bool</span>,
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">impl</span> <span class="ident">Settings</span> {
<span class="kw">pub</span> <span class="kw">fn</span> <span class="ident">new</span>() -&gt; <span class="prelude-ty">Result</span><span class="op">&lt;</span><span class="self">Self</span>, <span class="ident">ConfigError</span><span class="op">&gt;</span> {
<span class="kw">let</span> <span class="kw-2">mut</span> <span class="ident">s</span> <span class="op">=</span> <span class="ident">Config::new</span>();
<span class="kw">const</span> <span class="ident">CURRENT_DIR</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;./config/default.toml&quot;</span>;
<span class="kw">const</span> <span class="ident">ETC</span>: <span class="kw-2">&amp;</span><span class="ident">str</span> <span class="op">=</span> <span class="string">&quot;/etc/mcaptcha/config.toml&quot;</span>;
<span class="kw">if</span> <span class="kw">let</span> <span class="prelude-val">Ok</span>(<span class="ident">path</span>) <span class="op">=</span> <span class="ident">env::var</span>(<span class="string">&quot;MCAPTCHA_CONFIG&quot;</span>) {
<span class="ident">s</span>.<span class="ident">merge</span>(<span class="ident">File::with_name</span>(<span class="kw-2">&amp;</span><span class="ident">path</span>))<span class="question-mark">?</span>;
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">Path::new</span>(<span class="ident">CURRENT_DIR</span>).<span class="ident">exists</span>() {
<span class="comment">// merging default config from file</span>
<span class="ident">s</span>.<span class="ident">merge</span>(<span class="ident">File::with_name</span>(<span class="ident">CURRENT_DIR</span>))<span class="question-mark">?</span>;
} <span class="kw">else</span> <span class="kw">if</span> <span class="ident">Path::new</span>(<span class="ident">ETC</span>).<span class="ident">exists</span>() {
<span class="ident">s</span>.<span class="ident">merge</span>(<span class="ident">File::with_name</span>(<span class="ident">ETC</span>))<span class="question-mark">?</span>;
} <span class="kw">else</span> {
<span class="macro">log::warn!</span>(<span class="string">&quot;configuration file not found&quot;</span>);
}
<span class="ident">s</span>.<span class="ident">merge</span>(<span class="ident">Environment::with_prefix</span>(<span class="string">&quot;MCAPTCHA&quot;</span>).<span class="ident">separator</span>(<span class="string">&quot;_&quot;</span>))<span class="question-mark">?</span>;
<span class="ident">check_url</span>(<span class="kw-2">&amp;</span><span class="ident">s</span>);
<span class="kw">match</span> <span class="ident">env::var</span>(<span class="string">&quot;PORT&quot;</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">val</span>) =&gt; {
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;server.port&quot;</span>, <span class="ident">val</span>).<span class="ident">unwrap</span>();
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="macro">warn!</span>(<span class="string">&quot;couldn&#39;t interpret PORT: {}&quot;</span>, <span class="ident">e</span>),
}
<span class="kw">match</span> <span class="ident">env::var</span>(<span class="string">&quot;DATABASE_URL&quot;</span>) {
<span class="prelude-val">Ok</span>(<span class="ident">val</span>) =&gt; {
<span class="kw">let</span> <span class="ident">url</span> <span class="op">=</span> <span class="ident">Url::parse</span>(<span class="kw-2">&amp;</span><span class="ident">val</span>).<span class="ident">expect</span>(<span class="string">&quot;couldn&#39;t parse Database URL&quot;</span>);
<span class="kw">let</span> <span class="ident">database_conf</span> <span class="op">=</span> <span class="ident">DatabaseBuilder::extract_database_url</span>(<span class="kw-2">&amp;</span><span class="ident">url</span>);
<span class="ident">set_from_database_url</span>(<span class="kw-2">&amp;mut</span> <span class="ident">s</span>, <span class="kw-2">&amp;</span><span class="ident">database_conf</span>);
}
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="macro">warn!</span>(<span class="string">&quot;couldn&#39;t interpret DATABASE_URL: {}&quot;</span>, <span class="ident">e</span>),
}
<span class="ident">set_database_url</span>(<span class="kw-2">&amp;mut</span> <span class="ident">s</span>);
<span class="comment">// setting default values</span>
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">test</span>)]</span>
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;database.pool&quot;</span>, <span class="number">2</span>.<span class="ident">to_string</span>())
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t set database pool count&quot;</span>);
<span class="kw">match</span> <span class="ident">s</span>.<span class="ident">try_into</span>() {
<span class="prelude-val">Ok</span>(<span class="ident">val</span>) =&gt; <span class="prelude-val">Ok</span>(<span class="ident">val</span>),
<span class="prelude-val">Err</span>(<span class="ident">e</span>) =&gt; <span class="prelude-val">Err</span>(<span class="ident">ConfigError::Message</span>(<span class="macro">format!</span>(<span class="string">&quot;\n\nError: {}. If it says missing fields, then please refer to https://github.com/mCaptcha/mcaptcha#configuration to learn more about how mcaptcha reads configuration\n\n&quot;</span>, <span class="ident">e</span>))),
}
}
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">check_url</span>(<span class="ident">s</span>: <span class="kw-2">&amp;</span><span class="ident">Config</span>) {
<span class="kw">let</span> <span class="ident">url</span> <span class="op">=</span> <span class="ident">s</span>
.<span class="ident">get</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="string">&quot;source_code&quot;</span>)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access source_code&quot;</span>);
<span class="ident">Url::parse</span>(<span class="kw-2">&amp;</span><span class="ident">url</span>).<span class="ident">expect</span>(<span class="string">&quot;Please enter a URL for source_code in settings&quot;</span>);
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">set_from_database_url</span>(<span class="ident">s</span>: <span class="kw-2">&amp;mut</span> <span class="ident">Config</span>, <span class="ident">database_conf</span>: <span class="kw-2">&amp;</span><span class="ident">DatabaseBuilder</span>) {
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;database.username&quot;</span>, <span class="ident">database_conf</span>.<span class="ident">username</span>.<span class="ident">clone</span>())
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t set database username&quot;</span>);
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;database.password&quot;</span>, <span class="ident">database_conf</span>.<span class="ident">password</span>.<span class="ident">clone</span>())
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database password&quot;</span>);
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;database.hostname&quot;</span>, <span class="ident">database_conf</span>.<span class="ident">hostname</span>.<span class="ident">clone</span>())
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database hostname&quot;</span>);
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;database.port&quot;</span>, <span class="ident">database_conf</span>.<span class="ident">port</span> <span class="kw">as</span> <span class="ident">i64</span>)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database port&quot;</span>);
<span class="ident">s</span>.<span class="ident">set</span>(<span class="string">&quot;database.name&quot;</span>, <span class="ident">database_conf</span>.<span class="ident">name</span>.<span class="ident">clone</span>())
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database name&quot;</span>);
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">fn</span> <span class="ident">set_database_url</span>(<span class="ident">s</span>: <span class="kw-2">&amp;mut</span> <span class="ident">Config</span>) {
<span class="ident">s</span>.<span class="ident">set</span>(
<span class="string">&quot;database.url&quot;</span>,
<span class="macro">format!</span>(
<span class="string">r&quot;postgres://{}:{}@{}:{}/{}&quot;</span>,
<span class="ident">s</span>.<span class="ident">get</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="string">&quot;database.username&quot;</span>)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database username&quot;</span>),
<span class="ident">s</span>.<span class="ident">get</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="string">&quot;database.password&quot;</span>)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database password&quot;</span>),
<span class="ident">s</span>.<span class="ident">get</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="string">&quot;database.hostname&quot;</span>)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database hostname&quot;</span>),
<span class="ident">s</span>.<span class="ident">get</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="string">&quot;database.port&quot;</span>)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database port&quot;</span>),
<span class="ident">s</span>.<span class="ident">get</span>::<span class="op">&lt;</span><span class="ident">String</span><span class="op">&gt;</span>(<span class="string">&quot;database.name&quot;</span>)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t access database name&quot;</span>)
),
)
.<span class="ident">expect</span>(<span class="string">&quot;Couldn&#39;t set databse url&quot;</span>);
}
<span class="comment">//#[cfg(test)]</span>
<span class="comment">//mod tests {</span>
<span class="comment">// use super::*;</span>
<span class="comment">//</span>
<span class="comment">// #[test]</span>
<span class="comment">// fn url_prefix_test() {</span>
<span class="comment">// let mut settings = Settings::new().unwrap();</span>
<span class="comment">// assert!(settings.server.url_prefix.is_none());</span>
<span class="comment">// settings.server.url_prefix = Some(&quot;test&quot;.into());</span>
<span class="comment">// settings.server.check_url_prefix();</span>
<span class="comment">// settings.server.url_prefix = Some(&quot; &quot;.into());</span>
<span class="comment">// settings.server.check_url_prefix();</span>
<span class="comment">// assert!(settings.server.url_prefix.is_none());</span>
<span class="comment">// }</span>
<span class="comment">//</span>
<span class="comment">// #[test]</span>
<span class="comment">// fn smtp_config_works() {</span>
<span class="comment">// let settings = Settings::new().unwrap();</span>
<span class="comment">// assert!(settings.smtp.is_some());</span>
<span class="comment">// assert_eq!(settings.smtp.as_ref().unwrap().password, &quot;password&quot;);</span>
<span class="comment">// assert_eq!(settings.smtp.as_ref().unwrap().username, &quot;admin&quot;);</span>
<span class="comment">// }</span>
<span class="comment">//}</span>
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="tests_migrate" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>

View File

@@ -1,178 +0,0 @@
<!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 `src/tests-migrate.rs`."><meta name="keywords" content="rust, rustlang, rust-lang"><title>tests-migrate.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="../../tests_migrate/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="../../tests_migrate/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="../../tests_migrate/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>
</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">std::env</span>;
<span class="kw">use</span> <span class="ident">lazy_static::lazy_static</span>;
<span class="kw">use</span> <span class="ident">sqlx::postgres::PgPoolOptions</span>;
<span class="kw">mod</span> <span class="ident">settings</span>;
<span class="kw">pub</span> <span class="kw">use</span> <span class="ident">settings::Settings</span>;
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="macro">lazy_static!</span> {
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="kw">pub</span> <span class="kw">static</span> <span class="kw-2">ref</span> <span class="ident">SETTINGS</span>: <span class="ident">Settings</span> <span class="op">=</span> <span class="ident">Settings::new</span>().<span class="ident">unwrap</span>();
}
<span class="attribute">#[<span class="ident">cfg</span>(<span class="ident">not</span>(<span class="ident">tarpaulin_include</span>))]</span>
<span class="attribute">#[<span class="ident">actix_rt::main</span>]</span>
<span class="kw">async</span> <span class="kw">fn</span> <span class="ident">main</span>() {
<span class="kw">let</span> <span class="ident">db</span> <span class="op">=</span> <span class="ident">PgPoolOptions::new</span>()
.<span class="ident">max_connections</span>(<span class="ident">SETTINGS</span>.<span class="ident">database</span>.<span class="ident">pool</span>)
.<span class="ident">connect</span>(<span class="kw-2">&amp;</span><span class="ident">SETTINGS</span>.<span class="ident">database</span>.<span class="ident">url</span>)
.<span class="kw">await</span>
.<span class="ident">expect</span>(<span class="string">&quot;Unable to form database pool&quot;</span>);
<span class="kw">for</span> <span class="ident">arg</span> <span class="kw">in</span> <span class="ident">env::args</span>() {
<span class="kw">if</span> <span class="ident">arg</span> <span class="op">==</span> <span class="string">&quot;--build&quot;</span> {
<span class="macro">println!</span>(<span class="string">&quot;Building cache buster config&quot;</span>);
<span class="ident">build</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="ident">db</span>).<span class="kw">await</span>.<span class="ident">unwrap</span>();
}
<span class="kw">fn</span> <span class="ident">build</span>() {
<span class="kw">use</span> <span class="ident">std::process::Command</span>;
<span class="comment">// note: add error checking yourself.</span>
<span class="kw">let</span> <span class="ident">output</span> <span class="op">=</span> <span class="ident">Command::new</span>(<span class="string">&quot;git&quot;</span>)
.<span class="ident">args</span>(<span class="kw-2">&amp;</span>[<span class="string">&quot;rev-parse&quot;</span>, <span class="string">&quot;HEAD&quot;</span>])
.<span class="ident">output</span>()
.<span class="ident">unwrap</span>();
<span class="kw">let</span> <span class="ident">git_hash</span> <span class="op">=</span> <span class="ident">String::from_utf8</span>(<span class="ident">output</span>.<span class="ident">stdout</span>).<span class="ident">unwrap</span>();
<span class="macro">println!</span>(<span class="string">&quot;cargo:rustc-env=GIT_HASH={}&quot;</span>, <span class="ident">git_hash</span>);
<span class="ident">cache_bust</span>();
}
<span class="kw">fn</span> <span class="ident">cache_bust</span>() {
<span class="kw">use</span> <span class="ident">cache_buster::BusterBuilder</span>;
<span class="kw">let</span> <span class="ident">types</span> <span class="op">=</span> <span class="macro">vec!</span>[
<span class="ident">mime::IMAGE_PNG</span>,
<span class="ident">mime::IMAGE_SVG</span>,
<span class="ident">mime::IMAGE_JPEG</span>,
<span class="ident">mime::IMAGE_GIF</span>,
<span class="ident">mime::APPLICATION_JAVASCRIPT</span>,
<span class="ident">mime::TEXT_CSS</span>,
];
<span class="kw">let</span> <span class="ident">config</span> <span class="op">=</span> <span class="ident">BusterBuilder::default</span>()
.<span class="ident">source</span>(<span class="string">&quot;./static/cache&quot;</span>)
.<span class="ident">result</span>(<span class="string">&quot;./assets&quot;</span>)
.<span class="ident">mime_types</span>(<span class="ident">types</span>)
.<span class="ident">follow_links</span>(<span class="bool-val">true</span>)
.<span class="ident">build</span>()
.<span class="ident">unwrap</span>();
<span class="ident">config</span>.<span class="ident">process</span>().<span class="ident">unwrap</span>();
}
</code></pre></div>
</section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="tests_migrate" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.61.0 (fe5b13d68 2022-05-18)" ></div>
</body></html>