Added Main
This commit is contained in:
23
frontend/.gitignore
vendored
Normal file
23
frontend/.gitignore
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
node_modules
|
||||||
|
|
||||||
|
# Output
|
||||||
|
.output
|
||||||
|
.vercel
|
||||||
|
.netlify
|
||||||
|
.wrangler
|
||||||
|
/.svelte-kit
|
||||||
|
/build
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Env
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
!.env.test
|
||||||
|
|
||||||
|
# Vite
|
||||||
|
vite.config.js.timestamp-*
|
||||||
|
vite.config.ts.timestamp-*
|
||||||
1
frontend/.npmrc
Normal file
1
frontend/.npmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
engine-strict=true
|
||||||
38
frontend/README.md
Normal file
38
frontend/README.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# sv
|
||||||
|
|
||||||
|
Everything you need to build a Svelte project, powered by [`sv`](https://github.com/sveltejs/cli).
|
||||||
|
|
||||||
|
## Creating a project
|
||||||
|
|
||||||
|
If you're seeing this, you've probably already done this step. Congrats!
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# create a new project in the current directory
|
||||||
|
npx sv create
|
||||||
|
|
||||||
|
# create a new project in my-app
|
||||||
|
npx sv create my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
## Developing
|
||||||
|
|
||||||
|
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# or start the server and open the app in a new browser tab
|
||||||
|
npm run dev -- --open
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
To create a production version of your app:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
You can preview the production build with `npm run preview`.
|
||||||
|
|
||||||
|
> To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
|
||||||
13
frontend/jsconfig.json
Normal file
13
frontend/jsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"extends": "./.svelte-kit/tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"allowJs": true,
|
||||||
|
"checkJs": false,
|
||||||
|
"moduleResolution": "bundler"
|
||||||
|
}
|
||||||
|
// Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias
|
||||||
|
// except $lib which is handled by https://svelte.dev/docs/kit/configuration#files
|
||||||
|
//
|
||||||
|
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
|
||||||
|
// from the referenced tsconfig.json - TypeScript does not merge them in
|
||||||
|
}
|
||||||
1531
frontend/package-lock.json
generated
Normal file
1531
frontend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
frontend/package.json
Normal file
22
frontend/package.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "frontend",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.1",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite dev",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@sveltejs/adapter-auto": "^4.0.0",
|
||||||
|
"@sveltejs/adapter-node": "^5.2.12",
|
||||||
|
"@sveltejs/kit": "^2.0.0",
|
||||||
|
"@sveltejs/vite-plugin-svelte": "^4.0.0",
|
||||||
|
"svelte": "^5.0.0",
|
||||||
|
"vite": "^5.4.11"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@picocss/pico": "^2.0.6"
|
||||||
|
}
|
||||||
|
}
|
||||||
7
frontend/src/app.css
Normal file
7
frontend/src/app.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.title{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea{
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
17
frontend/src/app.html
Normal file
17
frontend/src/app.html
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>NoteApp</title>
|
||||||
|
%sveltekit.head%
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body data-sveltekit-preload-data="hover">
|
||||||
|
<div style="display: contents">%sveltekit.body%</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
51
frontend/src/lib/components/Note.svelte
Normal file
51
frontend/src/lib/components/Note.svelte
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<script>
|
||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import TimeAgo from "./TimeAgo.svelte";
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
|
||||||
|
function gotoEdit(){
|
||||||
|
goto(`editNote/${data.id}`);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
|
<div class="note" on:click={gotoEdit}>
|
||||||
|
<h2>{data.title}</h2>
|
||||||
|
<p>{data.content}</p>
|
||||||
|
<TimeAgo timestamp={data.createdOn}></TimeAgo>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.note {
|
||||||
|
background-color: rgba(0, 0, 0, 0.432);
|
||||||
|
width: 400px;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 25px;
|
||||||
|
border: 2px solid rgba(255, 255, 255, 0.432);
|
||||||
|
transition: transform 0.3s ease, box-shadow 0.3s ease;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
|
||||||
|
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note:hover {
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 0 16px rgba(255, 255, 255, 0.2);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note p {
|
||||||
|
text-align: left;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
41
frontend/src/lib/components/TimeAgo.svelte
Normal file
41
frontend/src/lib/components/TimeAgo.svelte
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<script>
|
||||||
|
// Aufräumen beim Verlassen der Komponente
|
||||||
|
import { onDestroy } from 'svelte';
|
||||||
|
|
||||||
|
export let timestamp;
|
||||||
|
|
||||||
|
let formattedTime;
|
||||||
|
|
||||||
|
// Funktion zur Berechnung von "Erstellt vor ..."
|
||||||
|
function timeAgo(inputTime) {
|
||||||
|
const date = new Date(inputTime);
|
||||||
|
const now = new Date();
|
||||||
|
const diff = Math.floor((now - date) / 1000); // Unterschied in Sekunden
|
||||||
|
|
||||||
|
if (diff < 60) return `Erstellt vor ${diff} Sekunden`;
|
||||||
|
if (diff < 3600) return `Erstellt vor ${Math.floor(diff / 60)} Minuten`;
|
||||||
|
if (diff < 86400) return `Erstellt vor ${Math.floor(diff / 3600)} Stunden`;
|
||||||
|
if (diff < 2592000) return `Erstellt vor ${Math.floor(diff / 86400)} Tagen`;
|
||||||
|
if (diff < 31536000) return `Erstellt vor ${Math.floor(diff / 2592000)} Monaten`;
|
||||||
|
return `Erstellt vor ${Math.floor(diff / 31536000)} Jahren`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aktualisiere den Zeitstempel alle 1 Sekunde
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
formattedTime = timeAgo(timestamp);
|
||||||
|
}, 10000);
|
||||||
|
|
||||||
|
// Berechne sofort die aktuelle Zeit
|
||||||
|
$: formattedTime = timeAgo(timestamp);
|
||||||
|
|
||||||
|
onDestroy(() => clearInterval(interval));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span class="timeStamp">{formattedTime}</span>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.timeStamp{
|
||||||
|
font-size: 15px;
|
||||||
|
color: #b4b4b4; /* Optional: für eine schönere Darstellung */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
1
frontend/src/lib/index.js
Normal file
1
frontend/src/lib/index.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// place files you want to import through the `$lib` alias in this folder.
|
||||||
21
frontend/src/routes/+error.svelte
Normal file
21
frontend/src/routes/+error.svelte
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<script>
|
||||||
|
import { page } from "$app/state";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1>{page.status}</h1>
|
||||||
|
<h2>{page.error.message}</h2>
|
||||||
|
<h3>Konkatiere uns, sollte der Fehler weiter Bestehen!</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.container{
|
||||||
|
text-align: center;
|
||||||
|
height: 80vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: -1000px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
30
frontend/src/routes/+layout.svelte
Normal file
30
frontend/src/routes/+layout.svelte
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<script>
|
||||||
|
import "../app.css";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="header">
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
<li id="appName"><strong>NoteApp</strong></li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/">Startseite</a></li>
|
||||||
|
<li><a href="/createNote">Neue Notiz</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot></slot>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#header{
|
||||||
|
padding: 15px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
padding-top: 10px;
|
||||||
|
width: 99.14vw;
|
||||||
|
}
|
||||||
|
|
||||||
|
#appName{
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
19
frontend/src/routes/+page.js
Normal file
19
frontend/src/routes/+page.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/** @type {import('./$types').LayoutServerLoad} */
|
||||||
|
export async function load({ fetch }) {
|
||||||
|
const response = await fetch("http://localhost:5165/api/note", {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!response.ok){
|
||||||
|
throw new Error(`Es gab einen Fehler beim Laden der Notizen: ${response.statusText}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
return {
|
||||||
|
notes: data
|
||||||
|
};
|
||||||
|
}
|
||||||
34
frontend/src/routes/+page.svelte
Normal file
34
frontend/src/routes/+page.svelte
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<script>
|
||||||
|
import Note from "$lib/components/Note.svelte";
|
||||||
|
export let data;
|
||||||
|
let notes = data.notes;
|
||||||
|
|
||||||
|
let notesSorted = notes.sort(
|
||||||
|
(a, b) => new Date(b.createdOn) - new Date(a.createdOn),
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div id="notes">
|
||||||
|
{#if notes.length === 0}
|
||||||
|
<h1 id="noNoteMsg">Es wurden noch keine Notizen geschrieben :(</h1>
|
||||||
|
{/if}
|
||||||
|
{#each notesSorted as note}
|
||||||
|
<Note data={note}></Note>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#notes {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: 15px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#noNoteMsg{
|
||||||
|
position: absolute;
|
||||||
|
top: 48%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
28
frontend/src/routes/createNote/+page.server.js
Normal file
28
frontend/src/routes/createNote/+page.server.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { goto } from '$app/navigation';
|
||||||
|
import { redirect } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
/** @satisfies {import('./$types').Actions} */
|
||||||
|
export const actions = {
|
||||||
|
create: async ({request}) => {
|
||||||
|
const formData = await request.formData();
|
||||||
|
const title = formData.get('title');
|
||||||
|
const content = formData.get('content');
|
||||||
|
|
||||||
|
const response = await fetch('http://localhost:5165/api/note', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({ title, content }),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json();
|
||||||
|
return { success: false, error: error.message || 'Failed to create note.' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
return goto("/")
|
||||||
|
}
|
||||||
|
}
|
||||||
51
frontend/src/routes/createNote/+page.svelte
Normal file
51
frontend/src/routes/createNote/+page.svelte
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<script>
|
||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import { error } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
let formData = { title: "", content: "" };
|
||||||
|
|
||||||
|
async function submitNote(event) {
|
||||||
|
const payload = {
|
||||||
|
title: formData.title,
|
||||||
|
content: formData.content,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch("http://localhost:5165/api/note", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
goto("/");
|
||||||
|
} else {
|
||||||
|
error(500, "Bad Request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="title">Erstelle eine Neue Notiz</h1>
|
||||||
|
|
||||||
|
<form on:submit|preventDefault={submitNote}>
|
||||||
|
<fieldset>
|
||||||
|
<label>
|
||||||
|
Titel
|
||||||
|
<input name="title" placeholder="Titel" bind:value={formData.title} />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Inhalt
|
||||||
|
<textarea
|
||||||
|
name="content"
|
||||||
|
placeholder="Inhalt"
|
||||||
|
bind:value={formData.content}
|
||||||
|
>
|
||||||
|
</textarea>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<input type="submit" value="Erstellen" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
16
frontend/src/routes/editNote/[id]/+page.js
Normal file
16
frontend/src/routes/editNote/[id]/+page.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { error } from '@sveltejs/kit';
|
||||||
|
|
||||||
|
/** @type {import('./$types').PageLoad} */
|
||||||
|
export async function load({ params, fetch }) {
|
||||||
|
const request = await fetch(`http://localhost:5165/api/note/${params.id}`)
|
||||||
|
|
||||||
|
const note = await request.json();
|
||||||
|
|
||||||
|
if(request.status != 200){
|
||||||
|
error(request.status, note.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
note
|
||||||
|
}
|
||||||
|
}
|
||||||
94
frontend/src/routes/editNote/[id]/+page.svelte
Normal file
94
frontend/src/routes/editNote/[id]/+page.svelte
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
<script>
|
||||||
|
import { goto } from "$app/navigation";
|
||||||
|
import TimeAgo from "$lib/components/TimeAgo.svelte";
|
||||||
|
import { error } from "@sveltejs/kit";
|
||||||
|
|
||||||
|
export let data;
|
||||||
|
const note = data.note;
|
||||||
|
|
||||||
|
let formData = { title: note.title, content: note.content };
|
||||||
|
|
||||||
|
async function changeNote() {
|
||||||
|
const payload = {
|
||||||
|
title: formData.title,
|
||||||
|
content: formData.content,
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await fetch(`http://localhost:5165/api/note/${note.id}`, {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
console.log(response.status)
|
||||||
|
if (response.ok) {
|
||||||
|
goto("/");
|
||||||
|
} else {
|
||||||
|
error(500, "Bad Request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteNote(){
|
||||||
|
const response = await fetch(`http://localhost:5165/api/note/${note.id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
goto("/");
|
||||||
|
} else {
|
||||||
|
error(500, "Bad Request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1 class="title">Ändere Notiz: {note.title}</h1>
|
||||||
|
|
||||||
|
<form on:submit|preventDefault={changeNote}>
|
||||||
|
<fieldset>
|
||||||
|
<label>
|
||||||
|
Titel
|
||||||
|
<input
|
||||||
|
name="title"
|
||||||
|
placeholder="Titel"
|
||||||
|
bind:value={formData.title}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Inhalt
|
||||||
|
<textarea
|
||||||
|
name="content"
|
||||||
|
placeholder="Inhalt"
|
||||||
|
bind:value={formData.content}
|
||||||
|
>
|
||||||
|
</textarea>
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<input type="submit" value="Ändern" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div class="button-container">
|
||||||
|
<button class="secondary" on:click={deleteNote}>Notiz Löschen</button>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<TimeAgo timestamp={note.createdOn}></TimeAgo>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.button-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center; /* Centers the button horizontally */
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
button{
|
||||||
|
width: 100%;
|
||||||
|
background-color: rgb(194, 43, 43);
|
||||||
|
border-color: rgba(255, 255, 255, 0);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
BIN
frontend/static/favicon.png
Normal file
BIN
frontend/static/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
13
frontend/svelte.config.js
Normal file
13
frontend/svelte.config.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import adapter from '@sveltejs/adapter-node';
|
||||||
|
|
||||||
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
|
const config = {
|
||||||
|
kit: {
|
||||||
|
// adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
|
||||||
|
// If your environment is not supported, or you settled on a specific environment, switch out the adapter.
|
||||||
|
// See https://svelte.dev/docs/kit/adapters for more information about adapters.
|
||||||
|
adapter: adapter()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
6
frontend/vite.config.js
Normal file
6
frontend/vite.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { sveltekit } from '@sveltejs/kit/vite';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [sveltekit()]
|
||||||
|
});
|
||||||
25
noteApi/.dockerignore
Normal file
25
noteApi/.dockerignore
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
**/.dockerignore
|
||||||
|
**/.env
|
||||||
|
**/.git
|
||||||
|
**/.gitignore
|
||||||
|
**/.project
|
||||||
|
**/.settings
|
||||||
|
**/.toolstarget
|
||||||
|
**/.vs
|
||||||
|
**/.vscode
|
||||||
|
**/.idea
|
||||||
|
**/*.*proj.user
|
||||||
|
**/*.dbmdl
|
||||||
|
**/*.jfm
|
||||||
|
**/azds.yaml
|
||||||
|
**/bin
|
||||||
|
**/charts
|
||||||
|
**/docker-compose*
|
||||||
|
**/Dockerfile*
|
||||||
|
**/node_modules
|
||||||
|
**/npm-debug.log
|
||||||
|
**/obj
|
||||||
|
**/secrets.dev.yaml
|
||||||
|
**/values.dev.yaml
|
||||||
|
LICENSE
|
||||||
|
README.md
|
||||||
13
noteApi/.idea/.idea.noteApi/.idea/.gitignore
generated
vendored
Normal file
13
noteApi/.idea/.idea.noteApi/.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/.idea.noteApi.iml
|
||||||
|
/modules.xml
|
||||||
|
/contentModel.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
4
noteApi/.idea/.idea.noteApi/.idea/encodings.xml
generated
Normal file
4
noteApi/.idea/.idea.noteApi/.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
||||||
8
noteApi/.idea/.idea.noteApi/.idea/indexLayout.xml
generated
Normal file
8
noteApi/.idea/.idea.noteApi/.idea/indexLayout.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
4
noteApi/.idea/.idea.noteApi/.idea/vcs.xml
generated
Normal file
4
noteApi/.idea/.idea.noteApi/.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings" defaultProject="true" />
|
||||||
|
</project>
|
||||||
96
noteApi/Controllers/AccountController.cs
Normal file
96
noteApi/Controllers/AccountController.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using noteApi.Dtos.Account;
|
||||||
|
using noteApi.Interfaces;
|
||||||
|
using noteApi.Models;
|
||||||
|
|
||||||
|
namespace noteApi.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/account")]
|
||||||
|
[ApiController]
|
||||||
|
public class AccountController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly UserManager<AppUser> _userManager;
|
||||||
|
private readonly ITokenService _tokenService;
|
||||||
|
private readonly SignInManager<AppUser> _signInManager;
|
||||||
|
public AccountController(UserManager<AppUser> userManager, ITokenService tokenService, SignInManager<AppUser> signInManager)
|
||||||
|
{
|
||||||
|
_userManager = userManager;
|
||||||
|
_tokenService = tokenService;
|
||||||
|
_signInManager = signInManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("register")]
|
||||||
|
public async Task<IActionResult> Register([FromBody] RegisterDto registerDto)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(!ModelState.IsValid)
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
|
||||||
|
var appUser = new AppUser
|
||||||
|
{
|
||||||
|
UserName = registerDto.Username,
|
||||||
|
Email = registerDto.Email
|
||||||
|
};
|
||||||
|
|
||||||
|
var createUser = await _userManager.CreateAsync(appUser, registerDto.Password);
|
||||||
|
|
||||||
|
if (createUser.Succeeded)
|
||||||
|
{
|
||||||
|
var roleResult = await _userManager.AddToRoleAsync(appUser, "User");
|
||||||
|
if (roleResult.Succeeded)
|
||||||
|
{
|
||||||
|
return Ok(new NewUserDto{
|
||||||
|
UserName = appUser.UserName,
|
||||||
|
Email = appUser.Email,
|
||||||
|
Token = _tokenService.CreateToken(appUser)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return StatusCode(500, roleResult.Errors);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return StatusCode(500, createUser.Errors);
|
||||||
|
}
|
||||||
|
} catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("login")]
|
||||||
|
public async Task<IActionResult> Login(LoginDto loginDto)
|
||||||
|
{
|
||||||
|
if (!ModelState.IsValid)
|
||||||
|
{
|
||||||
|
return BadRequest(ModelState);
|
||||||
|
}
|
||||||
|
|
||||||
|
var user = await _userManager.Users.FirstOrDefaultAsync(x => x.UserName == loginDto.Username.ToLower());
|
||||||
|
|
||||||
|
if(user == null)
|
||||||
|
{
|
||||||
|
return Unauthorized("Invalid username!");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = await _signInManager.CheckPasswordSignInAsync(user, loginDto.Password, false);
|
||||||
|
|
||||||
|
if (!result.Succeeded) return Unauthorized("Username not found and/or Password incorrect!");
|
||||||
|
|
||||||
|
return Ok(
|
||||||
|
new NewUserDto
|
||||||
|
{
|
||||||
|
UserName = user.UserName,
|
||||||
|
Email = user.Email,
|
||||||
|
Token = _tokenService.CreateToken(user)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
noteApi/Controllers/NoteController.cs
Normal file
73
noteApi/Controllers/NoteController.cs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using noteApi.Data;
|
||||||
|
using noteApi.Dtos.Note;
|
||||||
|
using noteApi.Interfaces;
|
||||||
|
|
||||||
|
namespace noteApi.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/note")]
|
||||||
|
[ApiController]
|
||||||
|
public class NoteController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly INoteRepository _noteRepo;
|
||||||
|
public NoteController(INoteRepository noteRepository)
|
||||||
|
{
|
||||||
|
_noteRepo = noteRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetAll()
|
||||||
|
{
|
||||||
|
var notes = await _noteRepo.GetAllAsync();
|
||||||
|
|
||||||
|
return Ok(notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<IActionResult> GetById([FromRoute] int id)
|
||||||
|
{
|
||||||
|
var note = await _noteRepo.GetByIdAsync(id);
|
||||||
|
|
||||||
|
if(note == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Create([FromBody] CreateNoteDto noteDto)
|
||||||
|
{
|
||||||
|
var note = await _noteRepo.CreateAsync(noteDto);
|
||||||
|
return CreatedAtAction(nameof(GetById), new { id = note.Id }, note);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}")]
|
||||||
|
public async Task<IActionResult> Update([FromRoute] int id, [FromBody] CreateNoteDto noteDto)
|
||||||
|
{
|
||||||
|
var note = await _noteRepo.UpdateAsync(id, noteDto);
|
||||||
|
|
||||||
|
if(note == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public async Task<IActionResult> Delete([FromRoute] int id)
|
||||||
|
{
|
||||||
|
var note = await _noteRepo.DeleteAsync(id);
|
||||||
|
|
||||||
|
if(note == null)
|
||||||
|
{
|
||||||
|
return NotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
noteApi/Controllers/StatusController.cs
Normal file
32
noteApi/Controllers/StatusController.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.VisualBasic;
|
||||||
|
using noteApi.Interfaces;
|
||||||
|
|
||||||
|
namespace noteApi.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/status")]
|
||||||
|
[ApiController]
|
||||||
|
public class StatusController : ControllerBase
|
||||||
|
{
|
||||||
|
public readonly INoteRepository _noteRepo;
|
||||||
|
public StatusController(INoteRepository noteRepository)
|
||||||
|
{
|
||||||
|
_noteRepo = noteRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> Get()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var stock = await _noteRepo.GetAllAsync();
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(503);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
noteApi/Data/ApplicationDbContext.cs
Normal file
34
noteApi/Data/ApplicationDbContext.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using noteApi.Models;
|
||||||
|
|
||||||
|
namespace noteApi.Data
|
||||||
|
{
|
||||||
|
public class ApplicationDbContext : IdentityDbContext<AppUser>
|
||||||
|
{
|
||||||
|
public ApplicationDbContext(DbContextOptions dbContextOptions) : base(dbContextOptions) { }
|
||||||
|
|
||||||
|
public DbSet<Note> Notes { get; set; }
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
base.OnModelCreating(builder);
|
||||||
|
|
||||||
|
List<IdentityRole> roles = new List<IdentityRole>{
|
||||||
|
new IdentityRole
|
||||||
|
{
|
||||||
|
Name = "Admin",
|
||||||
|
NormalizedName = "ADMIN"
|
||||||
|
},
|
||||||
|
new IdentityRole
|
||||||
|
{
|
||||||
|
Name = "User",
|
||||||
|
NormalizedName = "USER"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.Entity<IdentityRole>().HasData(roles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
noteApi/Dockerfile
Normal file
23
noteApi/Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
|
||||||
|
USER $APP_UID
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 8080
|
||||||
|
EXPOSE 8081
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["noteApi.csproj", "./"]
|
||||||
|
RUN dotnet restore "noteApi.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/"
|
||||||
|
RUN dotnet build "noteApi.csproj" -c $BUILD_CONFIGURATION -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
ARG BUILD_CONFIGURATION=Release
|
||||||
|
RUN dotnet publish "noteApi.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "noteApi.dll"]
|
||||||
12
noteApi/Dtos/Account/LoginDto.cs
Normal file
12
noteApi/Dtos/Account/LoginDto.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace noteApi.Dtos.Account
|
||||||
|
{
|
||||||
|
public class LoginDto
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string Username { get; set; }
|
||||||
|
[Required]
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
9
noteApi/Dtos/Account/NewUserDto.cs
Normal file
9
noteApi/Dtos/Account/NewUserDto.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace noteApi.Dtos.Account
|
||||||
|
{
|
||||||
|
public class NewUserDto
|
||||||
|
{
|
||||||
|
public string UserName { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string Token { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
15
noteApi/Dtos/Account/RegisterDto.cs
Normal file
15
noteApi/Dtos/Account/RegisterDto.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace noteApi.Dtos.Account
|
||||||
|
{
|
||||||
|
public class RegisterDto
|
||||||
|
{
|
||||||
|
[Required]
|
||||||
|
public string? Username { get; set; }
|
||||||
|
[Required]
|
||||||
|
[EmailAddress]
|
||||||
|
public string Email { get; set; }
|
||||||
|
[Required]
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
8
noteApi/Dtos/Note/CreateNoteDto.cs
Normal file
8
noteApi/Dtos/Note/CreateNoteDto.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
namespace noteApi.Dtos.Note
|
||||||
|
{
|
||||||
|
public class CreateNoteDto
|
||||||
|
{
|
||||||
|
public string Title { get; set; }
|
||||||
|
public string Content { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
noteApi/Interfaces/INoteRepository.cs
Normal file
14
noteApi/Interfaces/INoteRepository.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using noteApi.Dtos.Note;
|
||||||
|
using noteApi.Models;
|
||||||
|
|
||||||
|
namespace noteApi.Interfaces
|
||||||
|
{
|
||||||
|
public interface INoteRepository
|
||||||
|
{
|
||||||
|
Task<List<Note>> GetAllAsync();
|
||||||
|
Task<Note?> GetByIdAsync(int id);
|
||||||
|
Task<Note> CreateAsync(CreateNoteDto noteModel);
|
||||||
|
Task<Note?> UpdateAsync(int id, CreateNoteDto noteModel);
|
||||||
|
Task<Note?> DeleteAsync(int id);
|
||||||
|
}
|
||||||
|
}
|
||||||
9
noteApi/Interfaces/ITokenService.cs
Normal file
9
noteApi/Interfaces/ITokenService.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using noteApi.Models;
|
||||||
|
|
||||||
|
namespace noteApi.Interfaces
|
||||||
|
{
|
||||||
|
public interface ITokenService
|
||||||
|
{
|
||||||
|
string CreateToken(AppUser user);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
noteApi/Mappers/NoteMapper.cs
Normal file
17
noteApi/Mappers/NoteMapper.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using noteApi.Dtos.Note;
|
||||||
|
using noteApi.Models;
|
||||||
|
|
||||||
|
namespace noteApi.Mappers
|
||||||
|
{
|
||||||
|
public static class NoteMapper
|
||||||
|
{
|
||||||
|
public static Note ToNoteFromCreateDto(this CreateNoteDto noteDto)
|
||||||
|
{
|
||||||
|
return new Note
|
||||||
|
{
|
||||||
|
Title = noteDto.Title,
|
||||||
|
Content = noteDto.Content
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
315
noteApi/Migrations/20250208121510_Init.Designer.cs
generated
Normal file
315
noteApi/Migrations/20250208121510_Init.Designer.cs
generated
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using noteApi.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace noteApi.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ApplicationDbContext))]
|
||||||
|
[Migration("20250208121510_Init")]
|
||||||
|
partial class Init
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.12")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
|
||||||
|
b.HasData(
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = "1b10583c-a3d0-40ef-8e7e-a60aa00d6dba",
|
||||||
|
Name = "Admin",
|
||||||
|
NormalizedName = "ADMIN"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = "2cf905a9-68fa-4df8-8c4e-aa69c207b93b",
|
||||||
|
Name = "User",
|
||||||
|
NormalizedName = "USER"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("noteApi.Models.AppUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("noteApi.Models.Note", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedOn")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Notes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
294
noteApi/Migrations/20250208121510_Init.cs
Normal file
294
noteApi/Migrations/20250208121510_Init.cs
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace noteApi.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Init : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterDatabase()
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetRoles",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Name = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
NormalizedName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUsers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
UserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
NormalizedUserName = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
NormalizedEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
EmailConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
PasswordHash = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
SecurityStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ConcurrencyStamp = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
PhoneNumber = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
PhoneNumberConfirmed = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
TwoFactorEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
LockoutEnd = table.Column<DateTimeOffset>(type: "datetime(6)", nullable: true),
|
||||||
|
LockoutEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
AccessFailedCount = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Notes",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Title = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Content = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
CreatedOn = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Notes", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetRoleClaims",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ClaimType = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
|
||||||
|
column: x => x.RoleId,
|
||||||
|
principalTable: "AspNetRoles",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserClaims",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ClaimType = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ClaimValue = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserLogins",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ProviderKey = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ProviderDisplayName = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserRoles",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
RoleId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
|
||||||
|
column: x => x.RoleId,
|
||||||
|
principalTable: "AspNetRoles",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AspNetUserTokens",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
UserId = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
LoginProvider = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Name = table.Column<string>(type: "varchar(255)", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Value = table.Column<string>(type: "longtext", nullable: true)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "AspNetRoles",
|
||||||
|
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ "1b10583c-a3d0-40ef-8e7e-a60aa00d6dba", null, "Admin", "ADMIN" },
|
||||||
|
{ "2cf905a9-68fa-4df8-8c4e-aa69c207b93b", null, "User", "USER" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetRoleClaims_RoleId",
|
||||||
|
table: "AspNetRoleClaims",
|
||||||
|
column: "RoleId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "RoleNameIndex",
|
||||||
|
table: "AspNetRoles",
|
||||||
|
column: "NormalizedName",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetUserClaims_UserId",
|
||||||
|
table: "AspNetUserClaims",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetUserLogins_UserId",
|
||||||
|
table: "AspNetUserLogins",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_AspNetUserRoles_RoleId",
|
||||||
|
table: "AspNetUserRoles",
|
||||||
|
column: "RoleId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "EmailIndex",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
column: "NormalizedEmail");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "UserNameIndex",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
column: "NormalizedUserName",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetRoleClaims");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserClaims");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserLogins");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserRoles");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUserTokens");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Notes");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetRoles");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AspNetUsers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
312
noteApi/Migrations/ApplicationDbContextModelSnapshot.cs
Normal file
312
noteApi/Migrations/ApplicationDbContextModelSnapshot.cs
Normal file
@@ -0,0 +1,312 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using noteApi.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace noteApi.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ApplicationDbContext))]
|
||||||
|
partial class ApplicationDbContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "8.0.12")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||||
|
|
||||||
|
MySqlModelBuilderExtensions.AutoIncrementColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("RoleNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles", (string)null);
|
||||||
|
|
||||||
|
b.HasData(
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = "1b10583c-a3d0-40ef-8e7e-a60aa00d6dba",
|
||||||
|
Name = "Admin",
|
||||||
|
NormalizedName = "ADMIN"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = "2cf905a9-68fa-4df8-8c4e-aa69c207b93b",
|
||||||
|
Name = "User",
|
||||||
|
NormalizedName = "USER"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("noteApi.Models.AppUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("varchar(255)");
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp")
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256)
|
||||||
|
.HasColumnType("varchar(256)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasDatabaseName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasDatabaseName("UserNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("noteApi.Models.Note", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("Content")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedOn")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Title")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Notes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("noteApi.Models.AppUser", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
noteApi/Models/AppUser.cs
Normal file
9
noteApi/Models/AppUser.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
|
||||||
|
namespace noteApi.Models
|
||||||
|
{
|
||||||
|
public class AppUser : IdentityUser
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
10
noteApi/Models/Note.cs
Normal file
10
noteApi/Models/Note.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
namespace noteApi.Models
|
||||||
|
{
|
||||||
|
public class Note
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Title { get; set; } = string.Empty;
|
||||||
|
public string Content { get; set; } = string.Empty;
|
||||||
|
public DateTime CreatedOn { get; set; } = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
113
noteApi/Program.cs
Normal file
113
noteApi/Program.cs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.AspNetCore.Identity;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using noteApi.Data;
|
||||||
|
using noteApi.Interfaces;
|
||||||
|
using noteApi.Models;
|
||||||
|
using noteApi.Repository;
|
||||||
|
using noteApi.Service;
|
||||||
|
|
||||||
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
builder.Services.AddControllers();
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
builder.Services.AddSwaggerGen(option =>
|
||||||
|
{
|
||||||
|
option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo API", Version = "v1" });
|
||||||
|
option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
Description = "Please enter a valid token",
|
||||||
|
Name = "Authorization",
|
||||||
|
Type = SecuritySchemeType.Http,
|
||||||
|
BearerFormat = "JWT",
|
||||||
|
Scheme = "Bearer"
|
||||||
|
});
|
||||||
|
option.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Reference = new OpenApiReference
|
||||||
|
{
|
||||||
|
Type=ReferenceType.SecurityScheme,
|
||||||
|
Id="Bearer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new string[]{}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddDbContext<ApplicationDbContext>(options =>
|
||||||
|
options.UseMySql(builder.Configuration.GetConnectionString("DefaultConnection"),
|
||||||
|
new MySqlServerVersion(new Version(10, 5, 12)))); // Adjust version
|
||||||
|
|
||||||
|
builder.Services.AddIdentity<AppUser, IdentityRole>(options =>
|
||||||
|
{
|
||||||
|
options.Password.RequireDigit = true;
|
||||||
|
options.Password.RequiredLength = 4;
|
||||||
|
})
|
||||||
|
.AddEntityFrameworkStores<ApplicationDbContext>();
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(options =>
|
||||||
|
{
|
||||||
|
options.DefaultAuthenticateScheme =
|
||||||
|
options.DefaultChallengeScheme =
|
||||||
|
options.DefaultForbidScheme =
|
||||||
|
options.DefaultScheme =
|
||||||
|
options.DefaultSignInScheme =
|
||||||
|
options.DefaultSignOutScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
}).AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidIssuer = builder.Configuration["JWT:Issuer"],
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidAudience = builder.Configuration["JWT:Audience"],
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(
|
||||||
|
System.Text.Encoding.UTF8.GetBytes(builder.Configuration["JWT:SigningKey"])
|
||||||
|
)
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
|
||||||
|
|
||||||
|
builder.Services.AddCors(options =>
|
||||||
|
{
|
||||||
|
options.AddPolicy(name: MyAllowSpecificOrigins,
|
||||||
|
policy =>
|
||||||
|
{
|
||||||
|
policy.WithOrigins("http://localhost:5173", "http://localhost:7212")
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.AllowAnyMethod();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.Services.AddScoped<INoteRepository, NoteRepository>();
|
||||||
|
builder.Services.AddScoped<ITokenService, TokenService>();
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
app.UseCors(MyAllowSpecificOrigins);
|
||||||
|
|
||||||
|
app.UseAuthentication();
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.MapControllers();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
41
noteApi/Properties/launchSettings.json
Normal file
41
noteApi/Properties/launchSettings.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:22703",
|
||||||
|
"sslPort": 44323
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "http://localhost:5183",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"applicationUrl": "https://localhost:7029;http://localhost:5183",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "swagger",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
67
noteApi/Repository/NoteRepository.cs
Normal file
67
noteApi/Repository/NoteRepository.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using noteApi.Data;
|
||||||
|
using noteApi.Dtos.Note;
|
||||||
|
using noteApi.Interfaces;
|
||||||
|
using noteApi.Mappers;
|
||||||
|
using noteApi.Models;
|
||||||
|
|
||||||
|
namespace noteApi.Repository
|
||||||
|
{
|
||||||
|
public class NoteRepository : INoteRepository
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext _context;
|
||||||
|
public NoteRepository(ApplicationDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Note> CreateAsync(CreateNoteDto noteModel)
|
||||||
|
{
|
||||||
|
var note = noteModel.ToNoteFromCreateDto();
|
||||||
|
await _context.Notes.AddAsync(note);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Note?> DeleteAsync(int id)
|
||||||
|
{
|
||||||
|
var noteModel = await _context.Notes.FirstOrDefaultAsync(x => x.Id == id);
|
||||||
|
|
||||||
|
if (noteModel == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.Notes.Remove(noteModel);
|
||||||
|
_context.SaveChanges();
|
||||||
|
|
||||||
|
return noteModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Note>> GetAllAsync()
|
||||||
|
{
|
||||||
|
return await _context.Notes.ToListAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Note?> GetByIdAsync(int id)
|
||||||
|
{
|
||||||
|
return await _context.Notes.FindAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Note?> UpdateAsync(int id, CreateNoteDto noteModel)
|
||||||
|
{
|
||||||
|
var existingNote = await _context.Notes.FirstOrDefaultAsync(x => x.Id == id);
|
||||||
|
|
||||||
|
if (existingNote == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
existingNote.Title = noteModel.Title;
|
||||||
|
existingNote.Content = noteModel.Content;
|
||||||
|
_context.SaveChanges();
|
||||||
|
|
||||||
|
return existingNote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
44
noteApi/Service/TokenService.cs
Normal file
44
noteApi/Service/TokenService.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using noteApi.Interfaces;
|
||||||
|
using noteApi.Models;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace noteApi.Service
|
||||||
|
{
|
||||||
|
public class TokenService : ITokenService
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _config;
|
||||||
|
private readonly SymmetricSecurityKey _key;
|
||||||
|
public TokenService(IConfiguration config)
|
||||||
|
{
|
||||||
|
_config = config;
|
||||||
|
_key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["JWT:SigningKey"]));
|
||||||
|
}
|
||||||
|
public string CreateToken(AppUser user)
|
||||||
|
{
|
||||||
|
var claims = new List<Claim>
|
||||||
|
{
|
||||||
|
new Claim(JwtRegisteredClaimNames.Email, user.Email),
|
||||||
|
new Claim(JwtRegisteredClaimNames.GivenName, user.UserName)
|
||||||
|
};
|
||||||
|
|
||||||
|
var creds = new SigningCredentials(_key, SecurityAlgorithms.HmacSha256Signature);
|
||||||
|
var tokenDescriptor = new SecurityTokenDescriptor
|
||||||
|
{
|
||||||
|
Subject = new ClaimsIdentity(claims),
|
||||||
|
Expires = DateTime.Now.AddDays(14),
|
||||||
|
SigningCredentials = creds,
|
||||||
|
Issuer = _config["JWT:Issuer"],
|
||||||
|
Audience = _config["JWT:Audience"]
|
||||||
|
};
|
||||||
|
|
||||||
|
var tokenHandler = new JwtSecurityTokenHandler();
|
||||||
|
|
||||||
|
var token = tokenHandler.CreateToken(tokenDescriptor);
|
||||||
|
|
||||||
|
return tokenHandler.WriteToken(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
noteApi/appsettings.Development.json
Normal file
8
noteApi/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
noteApi/appsettings.json
Normal file
17
noteApi/appsettings.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Server=134.255.231.190;Port=5432;Database=noteApp;User Id=root;Password=34wa7JRRjqAdNRcKWrV1r7lvvkt5GDC0gwbQy93p5qLdKTeBUNZQfUYmAe9Urrip;"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"JWT": {
|
||||||
|
"Issuer": "http://localhost:5165",
|
||||||
|
"Audience": "http://localhost:5165",
|
||||||
|
"SigningKey": "o873LnblAWjhsuohfkop<jnojfpü<kjpjkoükpikneou980u3njdpisjk9unpß9esaSJJF"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
noteApi/bin/Debug/net8.0/Humanizer.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Humanizer.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.AspNetCore.OpenApi.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.AspNetCore.OpenApi.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.Bcl.AsyncInterfaces.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.Bcl.AsyncInterfaces.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.CodeAnalysis.CSharp.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.CodeAnalysis.CSharp.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.CodeAnalysis.Workspaces.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.CodeAnalysis.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.CodeAnalysis.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.EntityFrameworkCore.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.EntityFrameworkCore.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Caching.Memory.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Caching.Memory.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Identity.Core.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Identity.Core.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Logging.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Logging.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Options.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.Extensions.Options.dll
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.IdentityModel.Logging.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.IdentityModel.Logging.dll
Normal file
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.IdentityModel.Protocols.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.IdentityModel.Protocols.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.IdentityModel.Tokens.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.IdentityModel.Tokens.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Microsoft.OpenApi.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Microsoft.OpenApi.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Mono.TextTemplating.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Mono.TextTemplating.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/MySqlConnector.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/MySqlConnector.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Pomelo.EntityFrameworkCore.MySql.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Pomelo.EntityFrameworkCore.MySql.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Swashbuckle.AspNetCore.Swagger.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Swashbuckle.AspNetCore.Swagger.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Swashbuckle.AspNetCore.SwaggerGen.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Swashbuckle.AspNetCore.SwaggerGen.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/Swashbuckle.AspNetCore.SwaggerUI.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/Swashbuckle.AspNetCore.SwaggerUI.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/System.CodeDom.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/System.CodeDom.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/System.Composition.AttributedModel.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/System.Composition.AttributedModel.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/System.Composition.Convention.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/System.Composition.Convention.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/System.Composition.Hosting.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/System.Composition.Hosting.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/System.Composition.Runtime.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/System.Composition.Runtime.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/System.Composition.TypedParts.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/System.Composition.TypedParts.dll
Normal file
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/System.IdentityModel.Tokens.Jwt.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/System.IdentityModel.Tokens.Jwt.dll
Normal file
Binary file not shown.
8
noteApi/bin/Debug/net8.0/appsettings.Development.json
Normal file
8
noteApi/bin/Debug/net8.0/appsettings.Development.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
noteApi/bin/Debug/net8.0/appsettings.json
Normal file
17
noteApi/bin/Debug/net8.0/appsettings.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"DefaultConnection": "Server=134.255.231.190;Port=5432;Database=noteApp;User Id=root;Password=34wa7JRRjqAdNRcKWrV1r7lvvkt5GDC0gwbQy93p5qLdKTeBUNZQfUYmAe9Urrip;"
|
||||||
|
},
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft.AspNetCore": "Warning"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*",
|
||||||
|
"JWT": {
|
||||||
|
"Issuer": "http://localhost:5165",
|
||||||
|
"Audience": "http://localhost:5165",
|
||||||
|
"SigningKey": "o873LnblAWjhsuohfkop<jnojfpü<kjpjkoükpikneou980u3njdpisjk9unpß9esaSJJF"
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
noteApi/bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.resources.dll
Normal file
BIN
noteApi/bin/Debug/net8.0/cs/Microsoft.CodeAnalysis.resources.dll
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user