remove paywalls

This commit is contained in:
MuslemRahimi 2024-09-14 13:18:17 +02:00
parent 1760359d8a
commit dcd69e0f59
38 changed files with 2057 additions and 2021 deletions

View File

@ -247,7 +247,6 @@ function findLowestAndHighestFee(data, lastDateStr) {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if rawData?.length !== 0} {#if rawData?.length !== 0}
@ -336,12 +335,7 @@ function findLowestAndHighestFee(data, lastDateStr) {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -55,7 +55,6 @@
</div> </div>
</div> </div>
{#if data?.user?.tier === 'Pro'}
<!--Start Header--> <!--Start Header-->
<div class="bg-[#313131] w-fit relative flex flex-wrap items-center justify-center rounded-lg p-1 -mt-2"> <div class="bg-[#313131] w-fit relative flex flex-wrap items-center justify-center rounded-lg p-1 -mt-2">
{#each tabs as item, i} {#each tabs as item, i}
@ -94,12 +93,7 @@
{/if} {/if}
</span> </span>
</div> </div>
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</div> </div>

View File

@ -178,7 +178,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if rawData?.length !== 0} {#if rawData?.length !== 0}
<div class="mt-2 pb-8 sm:pb-2 rounded-lg bg-[#09090B] sm:bg-[#09090B]"> <div class="mt-2 pb-8 sm:pb-2 rounded-lg bg-[#09090B] sm:bg-[#09090B]">
@ -218,14 +217,8 @@ $: {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -226,7 +226,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if rawData?.length !== 0} {#if rawData?.length !== 0}
@ -317,12 +316,6 @@ $: {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -56,7 +56,6 @@ $: {
</div> </div>
</div> </div>
{#if data?.user?.tier === 'Pro'}
<div class="text-white text-[1rem] {latestInfoDate(rawData?.date) ? 'bg-[#F9AB00] bg-opacity-[0.1] p-3 rounded-lg' : 'bg-[#09090B] pl-3'} "> <div class="text-white text-[1rem] {latestInfoDate(rawData?.date) ? 'bg-[#F9AB00] bg-opacity-[0.1] p-3 rounded-lg' : 'bg-[#09090B] pl-3'} ">
<div class="mt-1">{$displayCompanyName} has released their quartely earnings on {new Date(rawData?.date)?.toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric', daySuffix: '2-digit' })}:</div> <div class="mt-1">{$displayCompanyName} has released their quartely earnings on {new Date(rawData?.date)?.toLocaleString('en-US', { month: 'short', day: 'numeric', year: 'numeric', daySuffix: '2-digit' })}:</div>
@ -67,12 +66,6 @@ $: {
EPS of <strong>${rawData?.eps}</strong> {rawData?.epsSurprise > 0 ? 'exceeds' : 'misses'} estimates by ${rawData?.epsSurprise?.toFixed(2)}, with <strong>{(((rawData?.eps - rawData?.epsPrior) / Math.abs(rawData?.epsPrior)) * 100)?.toFixed(2)}%</strong> YoY {((rawData?.eps - rawData?.epsPrior) / Math.abs(rawData?.epsPrior)) < 0 ? 'decline' : 'growth'}. EPS of <strong>${rawData?.eps}</strong> {rawData?.epsSurprise > 0 ? 'exceeds' : 'misses'} estimates by ${rawData?.epsSurprise?.toFixed(2)}, with <strong>{(((rawData?.eps - rawData?.epsPrior) / Math.abs(rawData?.epsPrior)) * 100)?.toFixed(2)}%</strong> YoY {((rawData?.eps - rawData?.epsPrior) / Math.abs(rawData?.epsPrior)) < 0 ? 'decline' : 'growth'}.
</li> </li>
</div> </div>
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</div> </div>

View File

@ -197,7 +197,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if rawData?.length !== 0} {#if rawData?.length !== 0}
<div class="mt-2 pb-4"> <div class="mt-2 pb-4">
@ -261,12 +260,6 @@ $: {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -255,7 +255,6 @@ function findLowestAndHighestPrice(data, lastDateStr) {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if rawData?.length !== 0} {#if rawData?.length !== 0}
@ -345,12 +344,7 @@ function findLowestAndHighestPrice(data, lastDateStr) {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -244,7 +244,6 @@ else {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if historyData?.length !== 0} {#if historyData?.length !== 0}
@ -391,12 +390,7 @@ else {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -54,7 +54,6 @@ $: {
</div> </div>
</div> </div>
{#if data?.user?.tier === 'Pro'}
<div class="text-white text-[1rem]"> <div class="text-white text-[1rem]">
{$displayCompanyName} is scheduled to release its earnings on {new Date(rawData?.date ?? null)?.toLocaleString('en-US', { {$displayCompanyName} is scheduled to release its earnings on {new Date(rawData?.date ?? null)?.toLocaleString('en-US', {
month: 'short', month: 'short',
@ -74,12 +73,7 @@ $: {
<strong>{revenueRatio}%</strong> YoY {revenueRatio > 0 ? 'growth' : revenueRatio < 0 ? 'shrinking' : ''} and earnings per share of <strong>{revenueRatio}%</strong> YoY {revenueRatio > 0 ? 'growth' : revenueRatio < 0 ? 'shrinking' : ''} and earnings per share of
<strong>{rawData?.epsEst}</strong>, making a <strong>{epsRatio}%</strong> {epsRatio > 0 ? 'increase' : epsRatio < 0 ? 'decrease' : ''} YoY. <strong>{rawData?.epsEst}</strong>, making a <strong>{epsRatio}%</strong> {epsRatio > 0 ? 'increase' : epsRatio < 0 ? 'decrease' : ''} YoY.
</div> </div>
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</div> </div>

View File

@ -153,7 +153,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
<div class="flex flex-row items-end justify-between"> <div class="flex flex-row items-end justify-between">
<select class="mt-5 sm:mb-0 ml-1 w-36 select select-bordered select-sm p-0 pl-5 bg-[#2A303C]" on:change={changeStatement}> <select class="mt-5 sm:mb-0 ml-1 w-36 select select-bordered select-sm p-0 pl-5 bg-[#2A303C]" on:change={changeStatement}>
@ -253,12 +252,7 @@ $: {
</div> </div>
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}

View File

@ -214,7 +214,6 @@
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if rawData?.length !== 0} {#if rawData?.length !== 0}
@ -268,12 +267,7 @@
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -213,7 +213,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if Object?.keys(priceAnalysisDict)?.length !== 0} {#if Object?.keys(priceAnalysisDict)?.length !== 0}
@ -322,13 +321,7 @@ $: {
</div> </div>
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -266,7 +266,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if Object?.keys(rawData)?.length !== 0} {#if Object?.keys(rawData)?.length !== 0}
@ -358,12 +357,7 @@ $: {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -95,7 +95,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if sentimentList?.length !== 0} {#if sentimentList?.length !== 0}
@ -238,13 +237,7 @@ $: {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -175,7 +175,6 @@ let charNumber = 30;
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if shareholderList?.length !== 0} {#if shareholderList?.length !== 0}
<div class="p-3 sm:p-0 mt-2 pb-8 sm:pb-2 rounded-lg bg-[#09090B] sm:bg-[#09090B]"> <div class="p-3 sm:p-0 mt-2 pb-8 sm:pb-2 rounded-lg bg-[#09090B] sm:bg-[#09090B]">
@ -395,12 +394,7 @@ let charNumber = 30;
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -179,7 +179,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if Object?.keys(rawData)?.length !== 0} {#if Object?.keys(rawData)?.length !== 0}
@ -293,12 +292,7 @@ $: {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -227,7 +227,6 @@
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if rawData?.length !== 0} {#if rawData?.length !== 0}
@ -300,13 +299,7 @@
</div> </div>
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -114,7 +114,6 @@ $: if ($assetType || $stockTicker || $etfTicker || $cryptoTicker) {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if signalList?.length !== 0} {#if signalList?.length !== 0}
@ -201,12 +200,7 @@ $: if ($assetType || $stockTicker || $etfTicker || $cryptoTicker) {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -103,7 +103,6 @@ $: {
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if trendList?.length !== 0} {#if trendList?.length !== 0}
<div class="w-full flex flex-col items-start"> <div class="w-full flex flex-col items-start">
@ -229,13 +228,7 @@ $: {
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -180,7 +180,6 @@ function getPlotOptions() {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if Object?.keys(varDict)?.length !== 0} {#if Object?.keys(varDict)?.length !== 0}
@ -239,13 +238,7 @@ function getPlotOptions() {
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -58,7 +58,6 @@ $: {
/> />
</div> </div>
{#if data?.user?.tier === 'Pro'}
{#if isLoaded} {#if isLoaded}
{#if wiim?.length !== 0} {#if wiim?.length !== 0}
<div class="mt-7"> <div class="mt-7">
@ -143,13 +142,7 @@ $: {
</div> </div>
</div> </div>
{/if} {/if}
{:else}
<div class="shadow-lg shadow-bg-[#000] bg-[#111112] sm:bg-opacity-[0.5] text-sm sm:text-[1rem] rounded-md w-full p-4 min-h-24 mt-4 text-white m-auto flex justify-center items-center text-center font-semibold">
<svg class="mr-1.5 w-5 h-5 inline-block"xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#A3A3A3" d="M17 9V7c0-2.8-2.2-5-5-5S7 4.2 7 7v2c-1.7 0-3 1.3-3 3v7c0 1.7 1.3 3 3 3h10c1.7 0 3-1.3 3-3v-7c0-1.7-1.3-3-3-3M9 7c0-1.7 1.3-3 3-3s3 1.3 3 3v2H9z"/></svg>
Unlock content with <a class="inline-block ml-2 text-blue-400 hover:sm:text-white" href="/pricing">Pro Subscription</a>
</div>
{/if}
</main> </main>
</section> </section>

View File

@ -581,7 +581,7 @@ $: {
</nav> </nav>
{#if data?.user?.tier === 'Free' || data?.user?.freeTrial === true} {#if !data?.user || data?.user?.tier === 'Free' || data?.user?.freeTrial === true}
<div class="pt-10 w-full mb-5 m-auto sticky"> <div class="pt-10 w-full mb-5 m-auto sticky">
<Card.Root <Card.Root
> >
@ -612,7 +612,7 @@ $: {
</Sheet.Content> </Sheet.Content>
</Sheet.Root> </Sheet.Root>
<a href="/home" class="-ml-2 flex flex-shrink-0"> <a href="/" class="-ml-2 flex flex-shrink-0">
<img class="avatar w-9 3xl:w-10 rounded-full" src={cloudFrontUrl+"/assets/stocknear_logo.png"} /> <img class="avatar w-9 3xl:w-10 rounded-full" src={cloudFrontUrl+"/assets/stocknear_logo.png"} />
<span class="text-white font-semibold ml-2 text-lg">Stocknear</span> <span class="text-white font-semibold ml-2 text-lg">Stocknear</span>
</a> </a>
@ -894,7 +894,7 @@ $: {
</a> </a>
</nav> </nav>
{#if data?.user?.tier === 'Free' || data?.user?.freeTrial === true} {#if !data?.user || data?.user?.tier === 'Free' || data?.user?.freeTrial === true}
<div class="mt-auto p-4 "> <div class="mt-auto p-4 ">
<Card.Root <Card.Root
data-x-chunk-name="dashboard-02-chunk-0" data-x-chunk-name="dashboard-02-chunk-0"

View File

@ -2,43 +2,38 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
async function checkDisposableEmail(email) { async function checkDisposableEmail(email) {
const url = `https://disposable.debounce.io/?email=${encodeURIComponent(email)}`; const url = `https://disposable.debounce.io/?email=${encodeURIComponent(email)}`;
const response = await fetch(url, { const response = await fetch(url, {
method: 'GET', method: "GET",
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json",
}, },
}); });
const output = (await response.json())?.disposable ?? false; const output = (await response.json())?.disposable ?? false;
return output return output;
} }
export const actions = { export const actions = {
login: async ({ request, locals }) => {
login: async ({ request, locals }) => { const { formData, errors } = await validateData(
const { formData, errors } = await validateData( await request.formData(),
await request.formData(), loginUserSchema
loginUserSchema, );
);
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors, errors: errors.fieldErrors,
}); });
} }
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
/* /*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -46,55 +41,55 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(301, "/pricing");
},
redirect(301, '/pricing'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
);
if (errors) {
return fail(400, {
data: formData,
errors: errors.fieldErrors,
});
}
const isEmailDisposable = await checkDisposableEmail(formData?.email);
if (isEmailDisposable === "true") {
error(400, "Disposable Email Addresses not allowed!");
}
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); //let username = generateUsername(formData.name.split(' ').join('')).toLowerCase();
if (errors) {
return fail(400, {
data: formData,
errors: errors.fieldErrors
});
}
const isEmailDisposable = await checkDisposableEmail(formData?.email);
if(isEmailDisposable === "true") { try {
error(400, 'Disposable Email Addresses not allowed!'); const newUser = await locals.pb.collection("users").create(formData);
} /*
await locals.pb?.collection('users').update(
newUser?.id, {
'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription
});
*/
await locals.pb.collection("users").requestVerification(formData.email);
} catch (err) {
console.log("Error: ", err);
error(err.status, err.message);
}
//let username = generateUsername(formData.name.split(' ').join('')).toLowerCase(); try {
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
try { /*
const newUser = await locals.pb.collection('users').create(formData);
await locals.pb?.collection('users').update(
newUser?.id, {
'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription
});
await locals.pb.collection('users').requestVerification(formData.email);
} catch (err) {
console.log('Error: ', err);
error(err.status, err.message);
}
try {
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -102,72 +97,74 @@ export const actions = {
}; };
} }
*/ */
} catch (err) { } catch (err) {
console.log("Error: ", err); console.log("Error: ", err);
error(err.status, err.message); error(err.status, err.message);
} }
redirect(301, "/pricing"); redirect(301, "/pricing");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/pricing", {httpOnly: true, cookies.set("provider", providerSelected, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("path", "/pricing", {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
redirect(302,authProviderRedirect); redirect(302, authProviderRedirect);
},
}
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +1,30 @@
import {getCache, setCache } from '$lib/store'; import { getCache, setCache } from "$lib/store";
import { redirect } from '@sveltejs/kit';
export const load = async ({ parent }) => {
const { apiKey, apiURL } = await parent();
export const load = async ({parent}) => { const getDashboard = async () => {
const { user } = await parent();
if (user) {
redirect(303, '/home');
}
const getFrontendStars = async () => {
let output;
// Get cached data for the specific tickerID // Get cached data for the specific tickerID
const cachedData = getCache('', 'getFrontendStars'); const cachedData = getCache("", "getDashboard");
if (cachedData) { if (cachedData) {
output = cachedData; return cachedData;
} else { } else {
const response = await fetch(apiURL + "/dashboard-info", {
// make the POST request to the endpoint method: "GET",
const response = await fetch('https://api.github.com/repos/stocknear/frontend', {
method: 'GET',
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json",
"X-API-KEY": apiKey,
}, },
}); });
output = (await response.json())['stargazers_count']; const output = await response?.json();
setCache('', output, 'getFrontendStars'); setCache("", output, "getDashboard");
return output;
} }
return output;
}; };
const getBackendStars = async () => {
let output;
// Get cached data for the specific tickerID
const cachedData = getCache('', 'getBackendStars');
if (cachedData) {
output = cachedData;
} else {
// make the POST request to the endpoint
const response = await fetch('https://api.github.com/repos/stocknear/backend', {
method: 'GET',
headers: {
"Content-Type": "application/json"
},
});
output = (await response.json())['stargazers_count'];
setCache('', output, 'getBackendStars');
}
return output;
};
// Make sure to return a promise // Make sure to return a promise
return { return {
getFrontendStars: await getFrontendStars(), getDashboard: await getDashboard(),
getBackendStars: await getBackendStars(),
}; };
}; };

View File

@ -2,6 +2,8 @@
import { numberOfUnreadNotification } from '$lib/store'; import { numberOfUnreadNotification } from '$lib/store';
export let data;
/* /*
import { intersect } from 'svelte-intersection-observer-action'; import { intersect } from 'svelte-intersection-observer-action';
@ -50,21 +52,21 @@
<!--Start Mission--> <!--Start Mission-->
<div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto sm:p-10 mt-3"> <div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto sm:p-10 mt-3">
<div class="text-white text-4xl sm:text-5xl text-center p-3 sm:mt-5"> <div class="text-white text-3xl sm:text-5xl text-center p-3 sm:mt-5">
<span class="font-bold"> <span class="font-bold">
A stock analysis platform by the users, for the users. A stock analysis platform by the users, for the users.
</span> </span>
</div> </div>
<div class="text-white text-lg mt-3 text-center pl-10 pr-10"> <div class="text-white text-[1rem] sm:text-lg mt-3 text-center px-5">
Our mission is to create the first large-scale stock analysis platform in which the platform's interests are aligned with those of the user—a platform founded on ethical design principles. At the heart of these principles is the concept of complete transparency, which is why the entire codebase is <a href="https://github.com/stocknear" rel="noopener noreferrer" target="_blank" class="text-blue-400 sm:hover:text-white sm:hover:underline" >open source</a>. Our mission is to create the first large-scale stock analysis platform in which the platform's interests are aligned with those of the user—a platform founded on ethical design principles. At the heart of these principles is the concept of complete transparency.
<!-- Start Image --> <!-- Start Image -->
<div class="m-auto flex justify-center mt-6"> <div class="m-auto flex justify-center mt-6">
<div class="relative"> <div class="relative">
<div class="z-1 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2"> <div class="z-1 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
<img class="w-28 mr-4" src={cloudFrontUrl+"/assets/globe.png"} alt="logo" loading="lazy"> <img class="w-24 sm:w-28 mr-4" src={cloudFrontUrl+"/assets/globe.png"} alt="logo" loading="lazy">
</div> </div>
<svg id="visual" viewBox="0 0 960 540" width="380" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"> <svg id="visual" viewBox="0 0 960 540" width="380" height="200" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs> <defs>
@ -87,17 +89,54 @@
</div> </div>
<!--End Mission--> <!--End Mission-->
<div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto pl-1 pr-1 sm:pl-0 sm:pr-0 pb-10 mb-8">
<div class="text-3xl sm:text-5xl text-white text-center p-3 ">
<span class="font-bold">
Proudly Open Source
</span>
</div>
<div class="text-[1rem] sm:text-lg text-white text-center w-11/12 sm:w-1/2 m-auto mb-8">
Stocknear is committed to open source & transparency. You can also run it locally or self-hosted.
</div>
<div class="w-11/12 sm:w-1/2 m-auto text-center">
<a href="https://github.com/stocknear" rel="noopener noreferrer" target="_blank"
class="w-fit sm:w-54 inline-flex animate-shine items-center justify-center rounded-xl text-sm border border-neutral-900 bg-[linear-gradient(110deg,#252626,55%,#fff,45%,#252626)] bg-[length:200%_100%] px-4 py-2 font-medium transition-colors"
>
<div class="m-auto flex-shrink-0 flex justify-center items-center">
<svg class="w-8 h-8 sm:w-10 sm:h-10" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="#fff" d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2"/></svg>
<span class="text-white text-[1rem] ml-2 font-semibold">
stocknear
{data?.getFrontendStars+data?.getBackendStars}
</span>
<svg class="ml-1 w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path fill="#fff" d="m18.7 4.627l2.247 4.31a2.27 2.27 0 0 0 1.686 1.189l4.746.65c2.538.35 3.522 3.479 1.645 5.219l-3.25 2.999a2.225 2.225 0 0 0-.683 2.04l.793 4.398c.441 2.45-2.108 4.36-4.345 3.24l-4.536-2.25a2.282 2.282 0 0 0-2.006 0l-4.536 2.25c-2.238 1.11-4.786-.79-4.345-3.24l.793-4.399c.14-.75-.12-1.52-.682-2.04l-3.251-2.998c-1.877-1.73-.893-4.87 1.645-5.22l4.746-.65a2.23 2.23 0 0 0 1.686-1.189l2.248-4.309c1.144-2.17 4.264-2.17 5.398 0"/></svg>
</div>
</a>
<div class="text-white text-sm font-semibold font-mono mt-5">
Leave a star to support us
</div>
</div>
</div>
<!-- Start Section--> <!-- Start Section-->
<div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto pl-1 pr-1 sm:pl-0 sm:pr-0 pb-10 mb-8"> <div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto pl-1 pr-1 sm:pl-0 sm:pr-0 pb-10 mb-8">
<div class="text-4xl sm:text-5xl text-white text-center p-3 mt-10 sm:mt-5"> <div class="text-3xl sm:text-5xl text-white text-center p-3 mt-10 sm:mt-5">
<span class="font-bold"> <span class="font-bold">
No ads. No tracking. No ads. No tracking.
</span> </span>
</div> </div>
<div class="text-white text-lg mt-3 text-center pl-10 pr-10"> <div class="text-white text-[1rem] sm:text-lg mt-3 text-center px-5">
Stocknear has no ads or affiliate marketing, or tracking. Stocknear has no ads or affiliate marketing, or tracking.
Your attention and data are never monetized. If you're skeptical, just look at our code <a href="https://github.com/stocknear" rel="noopener noreferrer" target="_blank" class="text-blue-400 sm:hover:text-white sm:hover:underline" >here</a>. Your attention and data are never monetized. If you're skeptical, just look at our code <a href="https://github.com/stocknear" rel="noopener noreferrer" target="_blank" class="text-blue-400 sm:hover:text-white sm:hover:underline" >here</a>.
</div> </div>
@ -107,14 +146,14 @@
<!-- Start Section--> <!-- Start Section-->
<div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto pb-10 mb-8"> <div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto pb-10 mb-8">
<div class="text-4xl sm:text-5xl text-white text-center p-3 mt-10 sm:mt-5"> <div class="text-3xl sm:text-5xl text-white text-center p-3 mt-10 sm:mt-5">
<span class="font-bold"> <span class="font-bold">
No Dark Patterns No Dark Patterns
</span> </span>
</div> </div>
<div class="text-white text-lg mt-3 text-center pl-10 pr-10"> <div class="text-white text-[1rem] sm:text-lg mt-3 text-center px-5">
On Stocknear, you won't encounter intrusive pop-ups prompting you to sign up unless it's essential for accessing all platform features. We don't manipulate you into using our platform more than you want to. If you wish to cancel your subscription, there's no survey to fill out; you can cancel it in just 2 seconds. On Stocknear, you won't encounter intrusive pop-ups prompting you to sign up unless it's essential for accessing all platform features. We don't manipulate you into using our platform more than you want to. If you wish to cancel your subscription, there's no survey to fill out; you can cancel it in just 2 seconds.
</div> </div>
</div> </div>
@ -122,13 +161,13 @@
<!--Start Why we need this --> <!--Start Why we need this -->
<div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto pb-10 mb-8"> <div class="bg-[#09090B] w-full hover:border-slate-500 border-slate-600 h-auto pb-10 mb-8">
<div class="text-4xl sm:text-5xl text-white text-center p-3 mt-10 sm:mt-5"> <div class="text-3xl sm:text-5xl text-white text-center p-3 mt-10 sm:mt-5">
<span class="font-bold"> <span class="font-bold">
What we offer What we offer
</span> </span>
</div> </div>
<div class="text-white text-lg mt-3 text-center pl-3 pr-3 sm:pl-10 sm:pr-10"> <div class="text-white text-[1rem] sm:text-lg mt-3 text-center pl-3 pr-3 sm:pl-10 sm:pr-10">
We provide retail traders with high-quality, accurate data that is only available to hedge funds and institutional investors. By bridging the gap between <span class="text-[#FBCE3C] font-semibold italic">Wall Street</span> and <span class="text-[#FBCE3C] font-semibold italic">Retail Traders</span>, we enhance your stock analysis with a wide range of data sources. Take control of your investments, make informed decisions, and execute profitable trades using our comprehensive data presented in an intuitive UI. We provide retail traders with high-quality, accurate data that is only available to hedge funds and institutional investors. By bridging the gap between <span class="text-[#FBCE3C] font-semibold italic">Wall Street</span> and <span class="text-[#FBCE3C] font-semibold italic">Retail Traders</span>, we enhance your stock analysis with a wide range of data sources. Take control of your investments, make informed decisions, and execute profitable trades using our comprehensive data presented in an intuitive UI.
<!-- Start Image --> <!-- Start Image -->
<div class="m-auto flex justify-center mt-5"> <div class="m-auto flex justify-center mt-5">
@ -160,13 +199,13 @@
<!--Start Why we need this --> <!--Start Why we need this -->
<div class="bg-[#09090B] w-full bg-[#09090B] sm:border-t hover:border-slate-500 border-slate-600 h-auto sm:p-10 mt-3 mb-20 sm:mb-8"> <div class="bg-[#09090B] w-full bg-[#09090B] sm:border-t hover:border-slate-500 border-slate-600 h-auto sm:p-10 mt-3 mb-20 sm:mb-8">
<div class="text-4xl sm:text-5xl font-bold text-white text-center p-3 mt-10 sm:mt-5"> <div class="text-3xl sm:text-5xl font-bold text-white text-center p-3 mt-10 sm:mt-5">
<span class="font-bold"> <span class="font-bold">
Why choose us Why choose us
</span> </span>
</div> </div>
<div class="-mt-10 sm:mt-0 text-white text-lg text-center pl-3 pr-3 sm:pl-10 sm:pr-10"> <div class="-mt-10 sm:mt-0 text-white text-[1rem] sm:text-lg text-center pl-3 pr-3 sm:pl-10 sm:pr-10">
<br class="mb-8 sm:mb-5"> <br class="mb-8 sm:mb-5">
We love data and want to understand what drives the stock market. We love data and want to understand what drives the stock market.
We collaborate with top data vendors to provide clear and actionable insights, giving you a competitive advantage over other traders. We collaborate with top data vendors to provide clear and actionable insights, giving you a competitive advantage over other traders.
@ -210,11 +249,11 @@
<!--Start Team --> <!--Start Team -->
<div class="bg-[#09090B] w-full bg-[#09090B] sm:border-t hover:border-slate-500 border-slate-600 h-auto sm:p-10 mt-3"> <div class="bg-[#09090B] w-full bg-[#09090B] sm:border-t hover:border-slate-500 border-slate-600 h-auto sm:p-10 mt-3">
<div class="text-4xl sm:text-5xl font-bold text-white text-center p-3 mt-10 sm:mt-5"> <div class="text-3xl sm:text-5xl font-bold text-white text-center p-3 mt-10 sm:mt-5">
Team Team
</div> </div>
<div class="text-white text-lg mt-3 text-center"> <div class="text-white text-[1rem] sm:text-lg mt-3 text-center">
<!-- Team members --> <!-- Team members -->
<div class="sm:flex sm:flex-wrap sm:justify-center mb-4"> <div class="sm:flex sm:flex-wrap sm:justify-center mb-4">
<!-- 1st member --> <!-- 1st member -->

60
src/routes/about/+page.ts Normal file
View File

@ -0,0 +1,60 @@
import { getCache, setCache } from "$lib/store";
import { redirect } from "@sveltejs/kit";
export const load = async ({ parent }) => {
const getFrontendStars = async () => {
let output;
// Get cached data for the specific tickerID
const cachedData = getCache("", "getFrontendStars");
if (cachedData) {
output = cachedData;
} else {
// make the POST request to the endpoint
const response = await fetch(
"https://api.github.com/repos/stocknear/frontend",
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
}
);
output = (await response.json())["stargazers_count"];
setCache("", output, "getFrontendStars");
}
return output;
};
const getBackendStars = async () => {
let output;
// Get cached data for the specific tickerID
const cachedData = getCache("", "getBackendStars");
if (cachedData) {
output = cachedData;
} else {
// make the POST request to the endpoint
const response = await fetch(
"https://api.github.com/repos/stocknear/backend",
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
}
);
output = (await response.json())["stargazers_count"];
setCache("", output, "getBackendStars");
}
return output;
};
// Make sure to return a promise
return {
getFrontendStars: await getFrontendStars(),
getBackendStars: await getBackendStars(),
};
};

View File

@ -2,29 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
const { formData, errors } = await validateData(
await request.formData(),
loginUserSchema
);
login: async ({ request, locals }) => { if (errors) {
const { formData, errors } = await validateData( return fail(400, {
await request.formData(), data: formData,
loginUserSchema, errors: errors.fieldErrors,
); });
}
if (errors) { try {
return fail(400, { await locals.pb
data: formData, .collection("users")
errors: errors.fieldErrors, .authWithPassword(formData.email, formData.password);
});
}
try { /*
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -32,113 +29,114 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(303, "/");
},
redirect(303, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/community", {httpOnly: true, cookies.set("provider", providerSelected, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); cookies.set("path", "/community", {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
} redirect(302, authProviderRedirect);
},
}; };

View File

@ -2,29 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
const { formData, errors } = await validateData(
await request.formData(),
loginUserSchema
);
login: async ({ request, locals }) => { if (errors) {
const { formData, errors } = await validateData( return fail(400, {
await request.formData(), data: formData,
loginUserSchema, errors: errors.fieldErrors,
); });
}
if (errors) { try {
return fail(400, { await locals.pb
data: formData, .collection("users")
errors: errors.fieldErrors, .authWithPassword(formData.email, formData.password);
});
}
try { /*
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -32,113 +29,114 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(303, "/community");
},
redirect(303, '/community'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/community"); redirect(303, "/community");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/community", {httpOnly: true, cookies.set("provider", providerSelected, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); cookies.set("path", "/community", {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
} redirect(302, authProviderRedirect);
},
}; };

View File

@ -2,46 +2,40 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const load = async ({locals, params}) => { export const load = async ({ locals, params }) => {
if (params.userId === locals?.user?.id) {
redirect(303, "/community/profile");
}
const userId = async () => {
if (params.userId === locals?.user?.id) { return params.userId;
redirect(303, '/community/profile'); };
}
const userId = async () => { return {
return params.userId userId: await userId(),
}; };
};
return {
userId: await userId(),
};
}
export const actions = { export const actions = {
login: async ({ request, locals }) => {
const { formData, errors } = await validateData(
await request.formData(),
loginUserSchema
);
login: async ({ request, locals }) => { if (errors) {
const { formData, errors } = await validateData( return fail(400, {
await request.formData(), data: formData,
loginUserSchema, errors: errors.fieldErrors,
); });
}
if (errors) { try {
return fail(400, { await locals.pb
data: formData, .collection("users")
errors: errors.fieldErrors, .authWithPassword(formData.email, formData.password);
});
}
try { /*
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -49,107 +43,106 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(303, "/");
},
redirect(303, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("provider", providerSelected, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); redirect(302, authProviderRedirect);
},
}
}; };

View File

@ -2,28 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
login: async ({ request, locals }) => { const { formData, errors } = await validateData(
const { formData, errors } = await validateData( await request.formData(),
await request.formData(), loginUserSchema
loginUserSchema, );
);
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors, errors: errors.fieldErrors,
}); });
} }
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
/* /*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -31,111 +29,114 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(302, "/");
},
redirect(302, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies, params }) => {
oauth2: async ( { url, locals, request, cookies, params }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/crypto/"+params.tickerID, {httpOnly: true, cookies.set("provider", providerSelected, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("path", "/crypto/" + params.tickerID, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
redirect(302,authProviderRedirect); redirect(302, authProviderRedirect);
},
}
}; };

View File

@ -2,29 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
const { formData, errors } = await validateData(
await request.formData(),
loginUserSchema
);
login: async ({ request, locals }) => { if (errors) {
const { formData, errors } = await validateData( return fail(400, {
await request.formData(), data: formData,
loginUserSchema, errors: errors.fieldErrors,
); });
}
if (errors) { try {
return fail(400, { await locals.pb
data: formData, .collection("users")
errors: errors.fieldErrors, .authWithPassword(formData.email, formData.password);
});
}
try { /*
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -32,113 +29,114 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(301, "/");
},
redirect(301, "/"); register: async ({ locals, request, params }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request, params }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/etf/"+params.tickerID); redirect(303, "/etf/" + params.tickerID);
}, },
oauth2: async ({ url, locals, request, cookies, params }) => {
oauth2: async ( { url, locals, request, cookies, params }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/etf/"+params.tickerID, {httpOnly: true, cookies.set("provider", providerSelected, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); cookies.set("path", "/etf/" + params.tickerID, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
} redirect(302, authProviderRedirect);
},
}; };

View File

@ -2,29 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
const { formData, errors } = await validateData(
await request.formData(),
loginUserSchema
);
login: async ({ request, locals }) => { if (errors) {
const { formData, errors } = await validateData( return fail(400, {
await request.formData(), data: formData,
loginUserSchema, errors: errors.fieldErrors,
); });
}
if (errors) { try {
return fail(400, { await locals.pb
data: formData, .collection("users")
errors: errors.fieldErrors, .authWithPassword(formData.email, formData.password);
});
}
try { /*
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -32,106 +29,106 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(302, "/");
},
redirect(302, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); cookies.set("provider", providerSelected, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60 * 60,
});
} redirect(302, authProviderRedirect);
},
}; };

View File

@ -2,7 +2,6 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
/* /*
export const load = async () => { export const load = async () => {
@ -30,29 +29,26 @@ export const load = async () => {
}; };
*/ */
export const actions = { export const actions = {
login: async ({ request, locals }) => {
login: async ({ request, locals }) => { const { formData, errors } = await validateData(
const { formData, errors } = await validateData( await request.formData(),
await request.formData(), loginUserSchema
loginUserSchema, );
);
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors, errors: errors.fieldErrors,
}); });
} }
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
/* /*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -60,112 +56,114 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(302, "/");
},
redirect(302, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/pricing", {httpOnly: true, cookies.set("provider", providerSelected, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("path", "/pricing", {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
redirect(302,authProviderRedirect); redirect(302, authProviderRedirect);
},
}
}; };

View File

@ -1,60 +1,61 @@
import { error, fail, redirect } from '@sveltejs/kit'; import { error, fail, redirect } from "@sveltejs/kit";
import { registerUserSchema } from '$lib/schemas'; import { registerUserSchema } from "$lib/schemas";
import { validateData } from '$lib/utils'; import { validateData } from "$lib/utils";
async function checkDisposableEmail(email) { async function checkDisposableEmail(email) {
const url = `https://disposable.debounce.io/?email=${encodeURIComponent(email)}`; const url = `https://disposable.debounce.io/?email=${encodeURIComponent(email)}`;
const response = await fetch(url, { const response = await fetch(url, {
method: 'GET', method: "GET",
headers: { headers: {
"Content-Type": "application/json" "Content-Type": "application/json",
}, },
}); });
const output = (await response.json())?.disposable ?? false; const output = (await response.json())?.disposable ?? false;
return output return output;
} }
export const actions = { export const actions = {
register: async ({ locals, request }) => { register: async ({ locals, request }) => {
const { formData, errors } = await validateData(
await request.formData(),
registerUserSchema
);
if (errors) {
return fail(400, {
data: formData,
errors: errors.fieldErrors,
});
}
const isEmailDisposable = await checkDisposableEmail(formData?.email);
if (isEmailDisposable === "true") {
error(400, "Disposable Email Addresses not allowed!");
}
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); //let username = generateUsername(formData.name.split(' ').join('')).toLowerCase();
if (errors) {
return fail(400, {
data: formData,
errors: errors.fieldErrors
});
}
const isEmailDisposable = await checkDisposableEmail(formData?.email);
if(isEmailDisposable === "true") { try {
error(400, 'Disposable Email Addresses not allowed!'); const newUser = await locals.pb.collection("users").create(formData);
} /*
await locals.pb?.collection('users').update(
newUser?.id, {
'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription
});
*/
await locals.pb.collection("users").requestVerification(formData.email);
} catch (err) {
console.log("Error: ", err);
error(err.status, err.message);
}
//let username = generateUsername(formData.name.split(' ').join('')).toLowerCase(); try {
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
try { /*
const newUser = await locals.pb.collection('users').create(formData);
await locals.pb?.collection('users').update(
newUser?.id, {
'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription
});
await locals.pb.collection('users').requestVerification(formData.email);
} catch (err) {
console.log('Error: ', err);
error(err.status, err.message);
}
try {
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -62,70 +63,74 @@ export const actions = {
}; };
} }
*/ */
} catch (err) { } catch (err) {
console.log("Error: ", err); console.log("Error: ", err);
error(err.status, err.message); error(err.status, err.message);
} }
redirect(301, "/"); redirect(301, "/");
}, },
oauth2: async ( { url, locals, request, cookies }) => {
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods();
const data = await request?.formData(); oauth2: async ({ url, locals, request, cookies }) => {
const providerSelected = data?.get('provider'); const authMethods = await locals?.pb
?.collection("users")
?.listAuthMethods();
if (!authMethods) { const data = await request?.formData();
return { const providerSelected = data?.get("provider");
authProviderRedirect: '',
authProviderState: ''
};
}
const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; if (!authMethods) {
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; return {
const state = provider.state; authProviderRedirect: "",
const verifier = provider.codeVerifier; authProviderState: "",
};
}
const redirectURL = `${url.origin}/oauth`;
cookies.set('state', state, {httpOnly: true, const targetItem = authMethods.authProviders?.findIndex(
sameSite: 'lax', (item) => item?.name === providerSelected
secure: true, );
path: '/', //console.log("==================")
maxAge: 60*60 //console.log(authMethods.authProviders)
}); //console.log('target item is: ', targetItem)
cookies.set('verifier', verifier, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/", {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("provider", providerSelected, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); cookies.set("path", "/", {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
} redirect(302, authProviderRedirect);
},
}; };

View File

@ -2,32 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
const { formData, errors } = await validateData(
await request.formData(),
loginUserSchema
);
login: async ({ request, locals }) => { if (errors) {
const { formData, errors } = await validateData( return fail(400, {
await request.formData(), data: formData,
loginUserSchema, errors: errors.fieldErrors,
); });
}
if (errors) { try {
return fail(400, { await locals.pb
data: formData, .collection("users")
errors: errors.fieldErrors, .authWithPassword(formData.email, formData.password);
});
}
try { /*
await locals.pb
.collection("users")
.authWithPassword(formData.email, formData.password);
/*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -35,106 +29,106 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(303, "/");
},
redirect(303, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("provider", providerSelected, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); redirect(302, authProviderRedirect);
},
}
}; };

View File

@ -2,28 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
login: async ({ request, locals }) => { const { formData, errors } = await validateData(
const { formData, errors } = await validateData( await request.formData(),
await request.formData(), loginUserSchema
loginUserSchema, );
);
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors, errors: errors.fieldErrors,
}); });
} }
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
/* /*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -31,114 +29,115 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(302, "/");
},
redirect(302, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
*/
await locals.pb.collection('users').requestVerification(formData.email); await locals.pb.collection("users").requestVerification(formData.email);
} catch (err) { } catch (err) {
console.log('Error: ', err); console.log("Error: ", err);
error(err.status, err.message); error(err.status, err.message);
} }
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies, params }) => {
oauth2: async ( { url, locals, request, cookies, params }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('path', "/stocks/"+params.tickerID, {httpOnly: true, cookies.set("provider", providerSelected, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("path", "/stocks/" + params.tickerID, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60,
});
redirect(302,authProviderRedirect); redirect(302, authProviderRedirect);
},
},
}; };

View File

@ -2,28 +2,26 @@ import { error, fail, redirect } from "@sveltejs/kit";
import { validateData } from "$lib/utils"; import { validateData } from "$lib/utils";
import { loginUserSchema, registerUserSchema } from "$lib/schemas"; import { loginUserSchema, registerUserSchema } from "$lib/schemas";
export const actions = { export const actions = {
login: async ({ request, locals }) => {
login: async ({ request, locals }) => { const { formData, errors } = await validateData(
const { formData, errors } = await validateData( await request.formData(),
await request.formData(), loginUserSchema
loginUserSchema, );
);
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors, errors: errors.fieldErrors,
}); });
} }
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
/* /*
if (!locals.pb?.authStore?.model?.verified) { if (!locals.pb?.authStore?.model?.verified) {
locals.pb.authStore.clear(); locals.pb.authStore.clear();
return { return {
@ -31,105 +29,106 @@ export const actions = {
}; };
} }
*/ */
} catch (err) {
} catch (err) { console.log("Error: ", err);
console.log("Error: ", err); error(err.status, err.message);
error(err.status, err.message); }
}
redirect(302, "/");
},
redirect(302, '/'); register: async ({ locals, request }) => {
}, const { formData, errors } = await validateData(
await request.formData(),
register: async ({ locals, request }) => { registerUserSchema
const { formData, errors } = await validateData(await request.formData(), registerUserSchema); );
if (errors) { if (errors) {
return fail(400, { return fail(400, {
data: formData, data: formData,
errors: errors.fieldErrors errors: errors.fieldErrors,
}); });
} }
try {
try { let newUser = await locals.pb.collection("users").create(formData);
let newUser = await locals.pb.collection('users').create(formData); /*
await locals.pb?.collection('users').update( await locals.pb?.collection('users').update(
newUser?.id, { newUser?.id, {
'freeTrial' : true, 'freeTrial' : true,
'tier': 'Pro', //Give new users a free trial for the Pro Subscription 'tier': 'Pro', //Give new users a free trial for the Pro Subscription
}); });
await locals.pb.collection('users').requestVerification(formData.email); */
} catch (err) { await locals.pb.collection("users").requestVerification(formData.email);
console.log('Error: ', err); } catch (err) {
error(err.status, err.message); console.log("Error: ", err);
} error(err.status, err.message);
}
try { try {
await locals.pb await locals.pb
.collection("users") .collection("users")
.authWithPassword(formData.email, formData.password); .authWithPassword(formData.email, formData.password);
} catch (err) {
console.log("Error: ", err);
} catch (err) { error(err.status, err.message);
console.log("Error: ", err); }
error(err.status, err.message);
}
redirect(303, "/"); redirect(303, "/");
}, },
oauth2: async ({ url, locals, request, cookies }) => {
oauth2: async ( { url, locals, request, cookies }) => { const authMethods = await locals?.pb
const authMethods = await locals?.pb?.collection('users')?.listAuthMethods(); ?.collection("users")
?.listAuthMethods();
const data = await request?.formData(); const data = await request?.formData();
const providerSelected = data?.get('provider'); const providerSelected = data?.get("provider");
if (!authMethods) { if (!authMethods) {
return { return {
authProviderRedirect: '', authProviderRedirect: "",
authProviderState: '' authProviderState: "",
}; };
} }
const redirectURL = `${url.origin}/oauth`; const redirectURL = `${url.origin}/oauth`;
const targetItem = authMethods.authProviders?.findIndex(item => item?.name === providerSelected );
//console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
const provider = authMethods.authProviders[targetItem]; const targetItem = authMethods.authProviders?.findIndex(
const authProviderRedirect = `${provider.authUrl}${redirectURL}`; (item) => item?.name === providerSelected
const state = provider.state; );
const verifier = provider.codeVerifier; //console.log("==================")
//console.log(authMethods.authProviders)
//console.log('target item is: ', targetItem)
cookies.set('state', state, {httpOnly: true, const provider = authMethods.authProviders[targetItem];
sameSite: 'lax', const authProviderRedirect = `${provider.authUrl}${redirectURL}`;
secure: true, const state = provider.state;
path: '/', const verifier = provider.codeVerifier;
maxAge: 60*60
});
cookies.set('verifier', verifier, {httpOnly: true, cookies.set("state", state, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set('provider', providerSelected, {httpOnly: true, cookies.set("verifier", verifier, {
sameSite: 'lax', httpOnly: true,
secure: true, sameSite: "lax",
path: '/', secure: true,
maxAge: 60*60 path: "/",
}); maxAge: 60 * 60,
});
cookies.set("provider", providerSelected, {
httpOnly: true,
sameSite: "lax",
secure: true,
path: "/",
maxAge: 60 * 60,
});
redirect(302,authProviderRedirect); redirect(302, authProviderRedirect);
},
}
}; };