Compare commits
5 Commits
9d00aa0e25
...
a1f278c83a
Author | SHA1 | Date |
---|---|---|
|
a1f278c83a | |
|
b4538d322a | |
|
78af7a8fa2 | |
|
37146568a8 | |
|
d332cd0d96 |
|
@ -0,0 +1,47 @@
|
|||
name: Dev testing pipeline
|
||||
run-name: ${{ gitea.actor }} is testing out Yuna 🚀
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
BuildAndTest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: List Base info 👓
|
||||
run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
||||
run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
|
||||
run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||
run: echo "${{ gitea.workspace }} is a workspace folder"
|
||||
|
||||
- name: Check out repo code 📝
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up PostgreSQL 🐘
|
||||
uses: postgres-actions/setup-postgres@v1
|
||||
with:
|
||||
postgres-version: '15'
|
||||
postgres-user: 'developer'
|
||||
postgres-password: 'magazinchik_forever'
|
||||
postgres-port: '5432'
|
||||
|
||||
- name: Init db 📜
|
||||
env:
|
||||
PGPSSWORD: magazinchik_forever
|
||||
run: |
|
||||
psql -h localhost -U developer -p 5432 -f ${{ gitea.workspace }}/Db/_localhost-2024_07_27_12_51_02-dump.sql
|
||||
|
||||
- name: Setup .NET 🛠️
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: '8.0.x'
|
||||
|
||||
- name: Restore dependencies 🔪
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build debug app ☢️
|
||||
run: donet build -c Debug --no-restore
|
||||
|
||||
- name: Run unit tests 💊
|
||||
run: dotnet test -c Debug --no-build
|
|
@ -1,19 +0,0 @@
|
|||
name: Gitea Actions Demo
|
||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
Explore-Gitea-Actions:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event."
|
||||
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!"
|
||||
- run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}."
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner."
|
||||
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
|
||||
- name: List files in the repository
|
||||
run: |
|
||||
ls ${{ gitea.workspace }}
|
||||
- run: echo "🍏 This job's status is ${{ job.status }}."
|
|
@ -0,0 +1,371 @@
|
|||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
-- Dumped from database version 15.2
|
||||
-- Dumped by pg_dump version 15.2
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
--
|
||||
-- Name: Yuna; Type: DATABASE; Schema: -; Owner: developer
|
||||
--
|
||||
|
||||
CREATE DATABASE "Yuna" WITH TEMPLATE = template0 ENCODING = 'UTF8' LOCALE_PROVIDER = libc LOCALE = 'Russian_Russia.1251';
|
||||
|
||||
|
||||
ALTER DATABASE "Yuna" OWNER TO developer;
|
||||
|
||||
\connect "Yuna"
|
||||
|
||||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Devices; Type: TABLE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE TABLE public."Yuna_Devices" (
|
||||
"Id" bigint NOT NULL,
|
||||
"Name" character varying(128) NOT NULL,
|
||||
"Description" character varying(255),
|
||||
"DeviceUrl" character varying(255),
|
||||
"UserId" bigint NOT NULL,
|
||||
"IsDeleted" boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Devices" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Devices_Id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."Yuna_Devices_Id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Devices_Id_seq" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Devices_Id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."Yuna_Devices_Id_seq" OWNED BY public."Yuna_Devices"."Id";
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props; Type: TABLE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE TABLE public."Yuna_Props" (
|
||||
"Id" bigint NOT NULL,
|
||||
"Name" character varying(100) NOT NULL,
|
||||
"MeasureName" character varying(255),
|
||||
"JsonValueName" character varying(255),
|
||||
"Type" smallint
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Props" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_Id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."Yuna_Props_Id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Props_Id_seq" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_Id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."Yuna_Props_Id_seq" OWNED BY public."Yuna_Props"."Id";
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices; Type: TABLE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE TABLE public."Yuna_Props_In_Devices" (
|
||||
"Id" bigint NOT NULL,
|
||||
"PropId" bigint NOT NULL,
|
||||
"DeviceId" bigint NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Props_In_Devices" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices_Id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."Yuna_Props_In_Devices_Id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Props_In_Devices_Id_seq" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices_Id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."Yuna_Props_In_Devices_Id_seq" OWNED BY public."Yuna_Props_In_Devices"."Id";
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Users; Type: TABLE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE TABLE public."Yuna_Users" (
|
||||
"Id" bigint NOT NULL,
|
||||
"Username" character varying(32) NOT NULL,
|
||||
"HashedPassword" character varying(255) NOT NULL,
|
||||
"IsAdmin" boolean NOT NULL
|
||||
);
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Users" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Users_Id_seq; Type: SEQUENCE; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public."Yuna_Users_Id_seq"
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
ALTER TABLE public."Yuna_Users_Id_seq" OWNER TO postgres;
|
||||
|
||||
--
|
||||
-- Name: Yuna_Users_Id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public."Yuna_Users_Id_seq" OWNED BY public."Yuna_Users"."Id";
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Devices Id; Type: DEFAULT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Devices" ALTER COLUMN "Id" SET DEFAULT nextval('public."Yuna_Devices_Id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props Id; Type: DEFAULT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Props" ALTER COLUMN "Id" SET DEFAULT nextval('public."Yuna_Props_Id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices Id; Type: DEFAULT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Props_In_Devices" ALTER COLUMN "Id" SET DEFAULT nextval('public."Yuna_Props_In_Devices_Id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Users Id; Type: DEFAULT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Users" ALTER COLUMN "Id" SET DEFAULT nextval('public."Yuna_Users_Id_seq"'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Data for Name: Yuna_Devices; Type: TABLE DATA; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (9, 'Test Device', 'Test descr', 'sdfsdfsdfsdf', 8, false);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (6, 'TenkiChan', 'Supa Weather', 'http://192.168.1.89/sensors', 8, false);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (3, 'Test Device', 'Test Description', 'Test Urldfg', 1, true);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (8, 'Test Devicedfgdfgdfgf', 'Test Description', 'Test Url11111111', 1, true);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (11, 'string', 'string', 'ffffffffffdgghfghfghfgfghfgfghfg', 8, true);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (12, 'Test Device', 'Test Description', 'Test Url', 1, true);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (13, 'Test Device', 'Test Description', 'Test Url', 1, true);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (10, 'string', 'string', 'fffdg', 8, true);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (4, 'Test Device', 'Nyanyanyadfgdfgfdgfdg', 'Test Urldfgdfgdfgdf', 1, false);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (1, 'strin111', 'strin', 'strindddd', 1, false);
|
||||
INSERT INTO public."Yuna_Devices" ("Id", "Name", "Description", "DeviceUrl", "UserId", "IsDeleted") VALUES (14, 'Test Device', 'Test Description', 'Test Url', 1, false);
|
||||
|
||||
|
||||
--
|
||||
-- Data for Name: Yuna_Props; Type: TABLE DATA; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (1, 'test', 'test', 'test', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (2, 'test', 'test', 'test', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (3, 'Temp', 'C', 'string', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (4, 'string', 'string', 'string', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (5, 'strding', 'strding', 'strding', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (6, 'SupaTest', 'testing', 'sssss', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (7, 'test', 'test', 'test', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (8, 'Температура', '°C', 'temperature', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (9, 'Влажность', '%', 'humidity', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (10, 'Концентрация CO2', 'см³/м³', 'ppm', 0);
|
||||
INSERT INTO public."Yuna_Props" ("Id", "Name", "MeasureName", "JsonValueName", "Type") VALUES (11, 'test', 'test', 'test', 0);
|
||||
|
||||
|
||||
--
|
||||
-- Data for Name: Yuna_Props_In_Devices; Type: TABLE DATA; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (1, 1, 1);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (21, 4, 1);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (22, 5, 1);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (32, 6, 1);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (39, 3, 1);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (40, 8, 6);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (41, 9, 6);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (42, 10, 6);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (43, 1, 9);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (44, 2, 9);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (45, 3, 9);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (46, 4, 9);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (47, 5, 10);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (48, 6, 10);
|
||||
INSERT INTO public."Yuna_Props_In_Devices" ("Id", "PropId", "DeviceId") VALUES (49, 5, 11);
|
||||
|
||||
|
||||
--
|
||||
-- Data for Name: Yuna_Users; Type: TABLE DATA; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (1, 'asd1', '2', true);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (2, 'test', '123', false);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (3, 'test', '123', false);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (4, 'test', '123', false);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (5, 'test', '123', false);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (6, 'test', '123', false);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (8, 'test1', 'EbvfS/o9GSL7wkbnix+BzMpCLJqfWqeTgimj3u9CknA=', false);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (7, 'vasich', 'V64zSeugpX/I4ZSqot7K0NQBOGdMNYNclXButwoXasI=', true);
|
||||
INSERT INTO public."Yuna_Users" ("Id", "Username", "HashedPassword", "IsAdmin") VALUES (9, 'test', '123', false);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Devices_Id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('public."Yuna_Devices_Id_seq"', 14, true);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_Id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('public."Yuna_Props_Id_seq"', 11, true);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices_Id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('public."Yuna_Props_In_Devices_Id_seq"', 49, true);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Users_Id_seq; Type: SEQUENCE SET; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
SELECT pg_catalog.setval('public."Yuna_Users_Id_seq"', 9, true);
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Devices Yuna_Devices_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Devices"
|
||||
ADD CONSTRAINT "Yuna_Devices_pkey" PRIMARY KEY ("Id");
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices Yuna_Props_In_Devices_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Props_In_Devices"
|
||||
ADD CONSTRAINT "Yuna_Props_In_Devices_pkey" PRIMARY KEY ("Id");
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props Yuna_Props_pkey; Type: CONSTRAINT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Props"
|
||||
ADD CONSTRAINT "Yuna_Props_pkey" PRIMARY KEY ("Id");
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Users_index_1; Type: INDEX; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX "Yuna_Users_index_1" ON public."Yuna_Users" USING btree ("Id");
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices Yuna_Props_In_Devices_relation_2; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Props_In_Devices"
|
||||
ADD CONSTRAINT "Yuna_Props_In_Devices_relation_2" FOREIGN KEY ("DeviceId") REFERENCES public."Yuna_Devices"("Id") ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Props_In_Devices Yuna_Props_In_Devices_relation_3; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Props_In_Devices"
|
||||
ADD CONSTRAINT "Yuna_Props_In_Devices_relation_3" FOREIGN KEY ("PropId") REFERENCES public."Yuna_Props"("Id") ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: Yuna_Devices fk_user_id; Type: FK CONSTRAINT; Schema: public; Owner: postgres
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public."Yuna_Devices"
|
||||
ADD CONSTRAINT fk_user_id FOREIGN KEY ("UserId") REFERENCES public."Yuna_Users"("Id");
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
|
@ -7,6 +7,7 @@ using System.Text.Json.Serialization;
|
|||
using Yuna.Website.Server.Services.TokenService;
|
||||
using Yuna.Website.Server.Model;
|
||||
using Yuna.Website.Server.Services.UserService;
|
||||
using Yuna.Website.Server.API.DTO;
|
||||
|
||||
namespace Yuna.Website.Server.API
|
||||
{
|
||||
|
@ -27,14 +28,7 @@ namespace Yuna.Website.Server.API
|
|||
|
||||
}
|
||||
|
||||
public class LoginRequest
|
||||
{
|
||||
[JsonPropertyName("password")]
|
||||
public string RawPassword { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("username")]
|
||||
public string UserName { get; set; } = null!;
|
||||
}
|
||||
|
||||
public async Task<IResult> Login(HttpContext context, [FromBody] LoginRequest request, IUserService userService, ITokenService tokenService)
|
||||
{
|
||||
var userFromDb = await userService.GetByUsername(request.UserName);
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Yuna.Website.Server.API.DTO
|
||||
{
|
||||
public class LoginRequest
|
||||
{
|
||||
[JsonPropertyName("password")]
|
||||
public string RawPassword { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("username")]
|
||||
public string UserName { get; set; } = null!;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,302 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using Yuna.Website.Server.API.DTO;
|
||||
using Yuna.Website.Server.Infrastructure;
|
||||
using Yuna.Website.Server.Services.OpenAuthService;
|
||||
using Yuna.Website.Server.Services.UserService;
|
||||
using Yuna.Website.Server.Storage.Repositories.UserBindings;
|
||||
|
||||
namespace Yuna.Website.Server.API
|
||||
{
|
||||
public class OpenAuthEndpoints
|
||||
{
|
||||
public void Define(WebApplication app)
|
||||
{
|
||||
app.MapGet("~/.well-known/openid-configuration", GetConfiguration)
|
||||
.WithTags("oauth");
|
||||
|
||||
app.MapMethods("/v1.0", ["HEAD"], Ping)
|
||||
.WithTags("oauth");
|
||||
|
||||
app.MapGet("api/oauth/login", LoginViaOauth)
|
||||
.WithTags("oauth");
|
||||
|
||||
app.MapPost("api/oauth/auth", AuthorizeViaOauth)
|
||||
.WithTags("oauth");
|
||||
|
||||
app.MapPost("/api/oauth/token", GetTokenByCode)
|
||||
.WithTags("oauth");
|
||||
}
|
||||
|
||||
public class DiscoveryResponse
|
||||
{
|
||||
[JsonPropertyName("issuer")]
|
||||
public string? Issuer { get; set; }
|
||||
|
||||
[JsonPropertyName("authorization_endpoint")]
|
||||
public string? AuthorizationEndpoint { get; set; }
|
||||
|
||||
[JsonPropertyName("token_endpoint")]
|
||||
public string? TokenEndpoint { get; set; }
|
||||
|
||||
[JsonPropertyName("token_endpoint_auth_methods_supported")]
|
||||
public IList<string>? TokenEndpointAuthMethodsSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("token_endpoint_auth_signing_alg_values_supported")]
|
||||
public IList<string>? TokenEndpointAuthSigningAlgValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("userinfo_endpoint")]
|
||||
public string? UserinfoEndpoint { get; set; }
|
||||
|
||||
[JsonPropertyName("check_session_iframe")]
|
||||
public string? CheckSessionIframe { get; set; }
|
||||
|
||||
[JsonPropertyName("end_session_endpoint")]
|
||||
public string? EndSessionEndpoint { get; set; }
|
||||
|
||||
[JsonPropertyName("jwks_uri")]
|
||||
public string? JwksUri { get; set; }
|
||||
|
||||
[JsonPropertyName("registration_endpoint")]
|
||||
public string? RegistrationEndpoint { get; set; }
|
||||
|
||||
[JsonPropertyName("scopes_supported")]
|
||||
public IList<string>? ScopesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("response_types_supported")]
|
||||
public IList<string>? ResponseTypesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("acr_values_supported")]
|
||||
public IList<string>? AcrValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("subject_types_supported")]
|
||||
public IList<string>? SubjectTypesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("userinfo_signing_alg_values_supported")]
|
||||
public IList<string>? UserinfoSigningAlgValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("userinfo_encryption_alg_values_supported")]
|
||||
public IList<string>? UserinfoEncryptionAlgValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("userinfo_encryption_enc_values_supported")]
|
||||
public IList<string>? UserinfoEncryptionEncValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("id_token_signing_alg_values_supported")]
|
||||
public IList<string>? IdTokenSigningAlgValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("id_token_encryption_alg_values_supported")]
|
||||
public IList<string>? IdTokenEncryptionAlgValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("id_token_encryption_enc_values_supported")]
|
||||
public IList<string>? IdTokenEncryptionEncValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("request_object_signing_alg_values_supported")]
|
||||
public IList<string>? RequestObjectSigningAlgValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("display_values_supported")]
|
||||
public IList<string>? DisplayValuesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("claim_types_supported")]
|
||||
public IList<string>? ClaimTypesSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("claims_supported")]
|
||||
public IList<string>? ClaimsSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("claims_parameter_supported")]
|
||||
public bool? ClaimsParameterSupported { get; set; }
|
||||
|
||||
[JsonPropertyName("service_documentation")]
|
||||
public string? ServiceDocumentation { get; set; }
|
||||
|
||||
[JsonPropertyName("ui_locales_supported")]
|
||||
public IList<string>? UiLocalesSupported { get; set; }
|
||||
}
|
||||
|
||||
public IResult GetConfiguration()
|
||||
{
|
||||
var response = new DiscoveryResponse()
|
||||
{
|
||||
Issuer = Settings.HttpsExternalUrl,
|
||||
AuthorizationEndpoint = Settings.HttpsExternalUrl + "/makaka",
|
||||
TokenEndpoint = Settings.HttpsExternalUrl + "/token",
|
||||
TokenEndpointAuthMethodsSupported = ["client_secret_basic", "private_key_jwt"],
|
||||
TokenEndpointAuthSigningAlgValuesSupported = ["RS256", "ES256"],
|
||||
|
||||
AcrValuesSupported = ["urn:mace:incommon:iap:silver", "urn:mace:incommon:iap:bronze"],
|
||||
ResponseTypesSupported = ["code", "code id_token", "id_token", "token id_token"],
|
||||
SubjectTypesSupported = [],
|
||||
|
||||
UserinfoEncryptionEncValuesSupported = ["A128CBC-HS256", "A128GCM"],
|
||||
IdTokenSigningAlgValuesSupported = ["RS256", "ES256", "HS256"],
|
||||
IdTokenEncryptionAlgValuesSupported = ["RSA1_5", "A128KW"],
|
||||
IdTokenEncryptionEncValuesSupported = ["A128CBC-HS256", "A128GCM"],
|
||||
|
||||
RequestObjectSigningAlgValuesSupported = ["none", "RS256", "ES256"],
|
||||
DisplayValuesSupported = ["page", "popup"],
|
||||
ClaimTypesSupported = ["normal", "distributed"],
|
||||
|
||||
|
||||
ScopesSupported = [],
|
||||
ClaimsSupported = [],
|
||||
ClaimsParameterSupported = false,
|
||||
ServiceDocumentation = null,
|
||||
UiLocalesSupported = ["ru-RU"],
|
||||
|
||||
};
|
||||
|
||||
return Results.Json(response);
|
||||
}
|
||||
|
||||
public IResult Ping()
|
||||
{
|
||||
return Results.Ok();
|
||||
}
|
||||
|
||||
public IResult LoginViaOauth(
|
||||
[FromQuery] string state,
|
||||
[FromQuery] string redirect_uri,
|
||||
[FromQuery] string response_type,
|
||||
[FromQuery] string client_id,
|
||||
HttpContext context,
|
||||
IOpenAuthService openAuthService)
|
||||
{
|
||||
|
||||
var host = context.Request.Host;
|
||||
if (!openAuthService.ValidateLoginRequest(response_type, client_id, host.Value))
|
||||
return Results.Unauthorized();
|
||||
|
||||
//TODO LOGIN PAGE URL IN SETTINGS
|
||||
return Results.Redirect($"https://localhost:5173/login?redirect_to={redirect_uri}&client_id={client_id}&state={state}");
|
||||
}
|
||||
|
||||
|
||||
public class OauthLoginRequest : LoginRequest
|
||||
{
|
||||
[JsonPropertyName("state")]
|
||||
public string State { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("redirectUri")]
|
||||
public string RedirectUri { get; set; } = null!;
|
||||
}
|
||||
public async Task<IResult> AuthorizeViaOauth([FromBody] OauthLoginRequest request, IUserService userService, IOpenAuthService openAuthService, HttpContext context)
|
||||
{
|
||||
var user = await userService.GetByUsername(request.UserName);
|
||||
|
||||
if (user is null) return Results.Problem(statusCode: 401, detail:"invalid user input data");
|
||||
|
||||
var inputHashedPassword = Encrypter.HashPassword(request.RawPassword, user.UserName);
|
||||
|
||||
if (!inputHashedPassword.Equals(user.HashedPassword)) return Results.Problem(statusCode: 401, detail: "invalid login attempt");
|
||||
|
||||
var binding = openAuthService.CreateBinding(user);
|
||||
|
||||
if(binding is null) return Results.Problem(statusCode: 401, detail: "Unable to create binding");
|
||||
|
||||
return Results.Ok(request.RedirectUri + $"?code={binding.Code}&state={request.State}");
|
||||
}
|
||||
|
||||
|
||||
public class OauthTokenResponse
|
||||
{
|
||||
[JsonPropertyName("access_token")]
|
||||
public string AccessToken { get; set; } = null!;
|
||||
|
||||
[JsonPropertyName("token_type")]
|
||||
public string TokenType => "Bearer";
|
||||
|
||||
[JsonPropertyName("expires_in")]
|
||||
public int ExpiresIn => int.MaxValue;
|
||||
}
|
||||
|
||||
public class TokenRequest
|
||||
{
|
||||
public string Code { get; set; }
|
||||
public string ClientId { get; set; } = null!;
|
||||
|
||||
public string ClientSecret { get; set; } = null!;
|
||||
|
||||
public string GrantType { get; set; } = null!;
|
||||
|
||||
public string RedirectUri { get; set; } = null!;
|
||||
}
|
||||
|
||||
public async Task<IResult> GetTokenByCode(
|
||||
HttpContext context,
|
||||
ILogger<OpenAuthEndpoints> logger,
|
||||
IOpenAuthService openAuthService)
|
||||
{
|
||||
var request = context.Request;
|
||||
var sb = new StringBuilder();
|
||||
// Записываем метод и URL запроса
|
||||
sb.AppendLine($"{request.Method} {request.Path}{request.QueryString}");
|
||||
|
||||
// Записываем заголовки
|
||||
sb.AppendLine("Headers:");
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
sb.AppendLine($"{header.Key}: {header.Value}");
|
||||
}
|
||||
|
||||
// Записываем тело запроса
|
||||
string bodyStr = "";
|
||||
sb.AppendLine("Body:");
|
||||
request.EnableBuffering(); // Для того чтобы можно было прочитать тело несколько раз
|
||||
using (var reader = new StreamReader(request.Body, Encoding.UTF8, leaveOpen: true))
|
||||
{
|
||||
var body = await reader.ReadToEndAsync();
|
||||
sb.AppendLine(body);
|
||||
bodyStr = body;
|
||||
request.Body.Position = 0; // Возвращаем позицию в начале потока
|
||||
}
|
||||
|
||||
logger.LogInformation(sb.ToString());
|
||||
|
||||
|
||||
|
||||
var tokenRequest = ParseQueryStringToTokenRequest(bodyStr);
|
||||
|
||||
|
||||
if (tokenRequest.GrantType != "authorization_code")
|
||||
{
|
||||
return Results.BadRequest(new { error = "unsupported_grant_type" });
|
||||
}
|
||||
|
||||
if(!tokenRequest.ClientId.Equals("vasich_yandex_server"))
|
||||
{
|
||||
return Results.BadRequest(new { error = "client id invalid" });
|
||||
}
|
||||
|
||||
if(!tokenRequest.ClientSecret.Equals("vasich_molodets_sdelal_oauth"))
|
||||
{
|
||||
return Results.BadRequest(new { error = "client secret invalid" });
|
||||
}
|
||||
|
||||
var userBinding = openAuthService.GetByCode(tokenRequest.Code);
|
||||
|
||||
if (userBinding is null) return Results.BadRequest(new { error = "Invalid binding" });
|
||||
|
||||
return Results.Ok(new OauthTokenResponse()
|
||||
{
|
||||
AccessToken = userBinding.AccessToken
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static TokenRequest ParseQueryStringToTokenRequest(string queryString)
|
||||
{
|
||||
var queryParams = queryString.Split('&')
|
||||
.Select(param => param.Split('='))
|
||||
.ToDictionary(pair => pair[0], pair => Uri.UnescapeDataString(pair[1]));
|
||||
|
||||
return new TokenRequest
|
||||
{
|
||||
Code = queryParams["code"],
|
||||
ClientId = queryParams["client_id"],
|
||||
ClientSecret = queryParams["client_secret"],
|
||||
GrantType = queryParams["grant_type"],
|
||||
RedirectUri = queryParams["redirect_uri"]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
"AppVariables": {
|
||||
"AccessTokenLifeTimeMinutes": 1,
|
||||
"RefreshTokenLifeTimeDays": 365,
|
||||
"ReferalCode": "#I_@m_g00d_guy_07_07_2024"
|
||||
"ReferalCode": "#I_@m_g00d_guy_07_07_2024",
|
||||
"HttpsExternalHost": "https://smarthome.vasich.keenetic.pro"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"BarcodeService": "http://localhost:7799/barcode",
|
||||
|
|
|
@ -27,5 +27,13 @@ namespace Yuna.Website.Server.Infrastructure
|
|||
var hashedSalt = _tokenHasher.ComputeHash(bytesStr);
|
||||
return Convert.ToBase64String(hashedSalt);
|
||||
}
|
||||
|
||||
public static string GenerateRandomString(int length)
|
||||
{
|
||||
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
Random random = new Random();
|
||||
return new string(Enumerable.Repeat(chars, length)
|
||||
.Select(s => s[random.Next(s.Length)]).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ namespace Yuna.Website.Server.Infrastructure
|
|||
public static string ReferalCode { get; private set; } = null!;
|
||||
public static string DbConnectionStr { get; private set; } = null!;
|
||||
|
||||
public static string HttpsExternalUrl { get; private set; } = null!;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
var jsonText = File.ReadAllText("globalSettings.json");
|
||||
|
@ -50,6 +52,7 @@ namespace Yuna.Website.Server.Infrastructure
|
|||
|
||||
private static void LoadAppVariables(JsonElement appVariablesStr)
|
||||
{
|
||||
HttpsExternalUrl = appVariablesStr.GetProperty("HttpsExternalHost").GetString() ?? throw new Exception("no https exernal host");
|
||||
ReferalCode = appVariablesStr.GetProperty("ReferalCode").GetString() ?? throw new Exception("No ref code");
|
||||
AccessTokenLifeTime = TimeSpan.FromSeconds(appVariablesStr.GetProperty("AccessTokenLifeTimeMinutes").GetInt32());
|
||||
RefreshTokenLifeTime = TimeSpan.FromDays(appVariablesStr.GetProperty("RefreshTokenLifeTimeDays").GetInt32());
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
namespace Yuna.Website.Server.Model
|
||||
{
|
||||
public class UserBinding
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string Code { get; set; } = null!;
|
||||
public string AccessToken { get; set; } = null!;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@
|
|||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5227"
|
||||
"applicationUrl": "http://192.168.1.2:5227"
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
|
@ -28,6 +28,17 @@
|
|||
"ASPNETCORE_HTTP_PORTS": "8080"
|
||||
},
|
||||
"publishAllPorts": true
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "swagger",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "https://192.168.1.2:5227"
|
||||
}
|
||||
},
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
|
@ -39,4 +50,4 @@
|
|||
"sslPort": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using Yuna.Website.Server.Model;
|
||||
|
||||
namespace Yuna.Website.Server.Services.OpenAuthService
|
||||
{
|
||||
public interface IOpenAuthService
|
||||
{
|
||||
public bool ValidateLoginRequest(string responseType, string clientId, string host);
|
||||
public UserBinding CreateBinding(User user);
|
||||
public UserBinding? GetByCode(string code);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
using Yuna.Website.Server.Infrastructure;
|
||||
using Yuna.Website.Server.Model;
|
||||
using Yuna.Website.Server.Storage.Repositories.UserBindings;
|
||||
|
||||
namespace Yuna.Website.Server.Services.OpenAuthService
|
||||
{
|
||||
public class OpenAuthService : IOpenAuthService
|
||||
{
|
||||
private readonly IUserBindingsRepository _userBindingsRepository;
|
||||
private readonly ILogger<OpenAuthService> _logger;
|
||||
public OpenAuthService(IUserBindingsRepository userBindingsRepository, ILogger<OpenAuthService> logger)
|
||||
{
|
||||
_userBindingsRepository = userBindingsRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public UserBinding CreateBinding(User user)
|
||||
{
|
||||
//Надо переделать, чтобы код и токен точно были уникальные
|
||||
var binding = new UserBinding()
|
||||
{
|
||||
AccessToken = Encrypter.GenerateRandomString(128),
|
||||
Code = Encrypter.GenerateRandomString(50),
|
||||
UserId = user.Id
|
||||
};
|
||||
|
||||
_logger.LogInformation("Created OauthBinding:\n" +
|
||||
"UserId: {0}\n" +
|
||||
"AccessToken: {1}\n" +
|
||||
"Code: {2}\n", user.Id, binding.Code, binding.AccessToken);
|
||||
|
||||
return _userBindingsRepository.Create(binding);
|
||||
}
|
||||
|
||||
public bool ValidateLoginRequest(string responseType, string clientId, string host)
|
||||
{
|
||||
_logger.LogInformation("Host: {0}", host);
|
||||
|
||||
var result = responseType.Equals("code") && clientId.Equals("vasich_yandex_server");
|
||||
|
||||
if (result) _logger.LogInformation("OauthRequest valid");
|
||||
else _logger.LogWarning("OauthRequest invalid");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public UserBinding? GetByCode(string code)
|
||||
{
|
||||
return _userBindingsRepository.GetUserBinding(code);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,12 +3,14 @@ using Yuna.Website.Server.API;
|
|||
using Yuna.Website.Server.Infrastructure;
|
||||
using Yuna.Website.Server.Services.DeviceService;
|
||||
using Yuna.Website.Server.Services.DeviceSkillService;
|
||||
using Yuna.Website.Server.Services.OpenAuthService;
|
||||
using Yuna.Website.Server.Services.TokenService;
|
||||
using Yuna.Website.Server.Services.UserService;
|
||||
using Yuna.Website.Server.Storage;
|
||||
using Yuna.Website.Server.Storage.Repositories.Device;
|
||||
using Yuna.Website.Server.Storage.Repositories.Prop;
|
||||
using Yuna.Website.Server.Storage.Repositories.User;
|
||||
using Yuna.Website.Server.Storage.Repositories.UserBindings;
|
||||
|
||||
namespace Yuna.Website.Server
|
||||
{
|
||||
|
@ -60,6 +62,7 @@ namespace Yuna.Website.Server
|
|||
|
||||
public static void DefineEndpoints(WebApplication app)
|
||||
{
|
||||
new OpenAuthEndpoints().Define(app);
|
||||
new AuthEndpoints().Define(app);
|
||||
new SkillsEndpoints().Define(app);
|
||||
new DeviceEndpoints().Define(app);
|
||||
|
@ -129,10 +132,13 @@ namespace Yuna.Website.Server
|
|||
builder.Services.AddScoped<IPropService, PropService>();
|
||||
builder.Services.AddScoped<ITokenService, TokenService>();
|
||||
builder.Services.AddScoped<IDeviceService, DeviceService>();
|
||||
builder.Services.AddScoped<IOpenAuthService, OpenAuthService>();
|
||||
|
||||
|
||||
builder.Services.AddScoped<IDeviceRepository, DeviceRepository>();
|
||||
builder.Services.AddScoped<IPropRepository, PropRepository>();
|
||||
builder.Services.AddScoped<IUserRepository, UserRepository>();
|
||||
builder.Services.AddScoped<IUserBindingsRepository, UserBindingRepository>();
|
||||
}
|
||||
|
||||
public static void DefineAuth(WebApplicationBuilder builder)
|
||||
|
@ -185,8 +191,8 @@ namespace Yuna.Website.Server
|
|||
builder.Services.AddSwaggerGen();
|
||||
|
||||
builder.Services.AddCors();
|
||||
|
||||
|
||||
|
||||
//builder.Services.AddAutoMapper(typeof(ApplicationProfile));
|
||||
}
|
||||
|
||||
|
@ -195,7 +201,14 @@ namespace Yuna.Website.Server
|
|||
{
|
||||
if (app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseCors(x => x.WithOrigins("https://localhost:5173", "http://localhost:5173").AllowAnyMethod().AllowAnyHeader().AllowCredentials());
|
||||
app.UseCors(x =>
|
||||
x.WithOrigins("https://localhost:5173", "http://localhost:5173", "https://192.168.1.2:5227")
|
||||
.AllowAnyMethod()
|
||||
.AllowAnyHeader()
|
||||
.AllowCredentials()
|
||||
.SetIsOriginAllowed(origin => true) // Разрешить все источники
|
||||
.WithExposedHeaders("Location")); // Разрешить заголовок Location)
|
||||
|
||||
}
|
||||
|
||||
else
|
||||
|
@ -207,12 +220,12 @@ namespace Yuna.Website.Server
|
|||
app.UseDefaultFiles();
|
||||
app.UseStaticFiles();
|
||||
|
||||
|
||||
|
||||
|
||||
app.Use(async (context, next) =>
|
||||
{
|
||||
var isLoggedIn = context.User?.Identity?.IsAuthenticated ?? false;
|
||||
if(context.Request.Path.StartsWithSegments("/login") && isLoggedIn)
|
||||
if (context.Request.Path.StartsWithSegments("/login") && isLoggedIn)
|
||||
{
|
||||
context.Response.Redirect("/");
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
using Yuna.Website.Server.Model;
|
||||
|
||||
namespace Yuna.Website.Server.Storage.Repositories.UserBindings
|
||||
{
|
||||
public interface IUserBindingsRepository
|
||||
{
|
||||
public UserBinding? GetUserBinding(string code);
|
||||
public UserBinding Create(UserBinding userBinding);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
using Yuna.Website.Server.Model;
|
||||
|
||||
namespace Yuna.Website.Server.Storage.Repositories.UserBindings
|
||||
{
|
||||
public class UserBindingRepository : IUserBindingsRepository
|
||||
{
|
||||
private static List<UserBinding> _inMemoryContext = new();
|
||||
|
||||
public UserBindingRepository() { }
|
||||
|
||||
public UserBinding Create(UserBinding userBinding)
|
||||
{
|
||||
userBinding.Id = _inMemoryContext.Count;
|
||||
_inMemoryContext.Add(userBinding);
|
||||
return userBinding;
|
||||
}
|
||||
|
||||
public UserBinding? GetUserBinding(string code)
|
||||
{
|
||||
var binding = _inMemoryContext.FirstOrDefault(x => x.Code.Equals(code));
|
||||
return binding;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,10 @@
|
|||
|
||||
import { api } from "../../services/Api";
|
||||
import { ILoginRequest, ILoginResult } from "./types";
|
||||
import { ILoginRequest, ILoginResult, IOauthLoginRequest } from "./types";
|
||||
|
||||
interface IOauthLoginResult extends ILoginResult {
|
||||
href: string | null;
|
||||
}
|
||||
|
||||
export class LoginPageService {
|
||||
public static async login(request: ILoginRequest): Promise<ILoginResult> {
|
||||
|
@ -18,4 +21,20 @@ export class LoginPageService {
|
|||
return { loggedIn: false, isError: true };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static async loginOauth(request: IOauthLoginRequest): Promise<IOauthLoginResult> {
|
||||
try {
|
||||
const response = await api.post<string>("/oauth/auth", request);
|
||||
if (response.status === 200) return { loggedIn: true, isError: false, href: response.data };
|
||||
|
||||
return { loggedIn: false, isError: false, href: null };
|
||||
}
|
||||
|
||||
catch (error) {
|
||||
console.error("Error: ", error);
|
||||
return { loggedIn: false, isError: true, href: null };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import { makeAutoObservable } from "mobx";
|
|||
import { LoginPageService } from "./LoginPageService";
|
||||
import { createStandaloneToast } from "@chakra-ui/react";
|
||||
import { error } from "../../utils/ToastHelper";
|
||||
import { IOauthQueryParams } from "./types";
|
||||
|
||||
|
||||
|
||||
|
@ -11,6 +12,17 @@ export class LoginPageStore {
|
|||
password: string = "";
|
||||
isLoading: boolean = false;
|
||||
|
||||
private getQueryParams(): IOauthQueryParams | null {
|
||||
const url = window.location.href;
|
||||
const urlObj = new URL(url);
|
||||
const params = new URLSearchParams(urlObj.search);
|
||||
|
||||
const redirectUri: string | null = params.get('redirect_to');
|
||||
const state: string | null = params.get('state');
|
||||
|
||||
if (state && redirectUri) return { redirectUri: redirectUri, state: state }
|
||||
return null;
|
||||
}
|
||||
|
||||
setLogin(value: string) {
|
||||
this.login = value;
|
||||
|
@ -22,7 +34,43 @@ export class LoginPageStore {
|
|||
}
|
||||
|
||||
async handleLogin() {
|
||||
const oauthParams = this.getQueryParams()
|
||||
|
||||
if (oauthParams) await this.loginAsOauth(oauthParams);
|
||||
else await this.loginSimpleWay()
|
||||
}
|
||||
|
||||
async loginAsOauth(oauthParams: IOauthQueryParams) {
|
||||
this.isLoading = true;
|
||||
|
||||
const result = await LoginPageService
|
||||
.loginOauth({
|
||||
password: this.password,
|
||||
username: this.login,
|
||||
redirectUri: oauthParams.redirectUri,
|
||||
state: oauthParams.state
|
||||
});
|
||||
this.isLoading = false;
|
||||
|
||||
if (result?.isError) {
|
||||
error("Ошибка", "Запрос не был выполнен")
|
||||
return;
|
||||
}
|
||||
|
||||
if (result && !result.loggedIn) {
|
||||
error("Неверный логин или пароль", "Проверьте еще раз")
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.replace(result.href!);
|
||||
|
||||
}
|
||||
|
||||
|
||||
async loginSimpleWay() {
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
const result = await LoginPageService.login({ password: this.password, username: this.login })
|
||||
this.isLoading = false;
|
||||
|
||||
|
|
|
@ -6,4 +6,11 @@ export interface ILoginResult {
|
|||
export interface ILoginRequest {
|
||||
password: string;
|
||||
username: string;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IOauthQueryParams {
|
||||
redirectUri: string;
|
||||
state: string;
|
||||
}
|
||||
|
||||
export interface IOauthLoginRequest extends IOauthQueryParams, ILoginRequest { }
|
|
@ -1,10 +1,10 @@
|
|||
import axios from "axios";
|
||||
|
||||
export const api = axios.create({
|
||||
baseURL: "http://localhost:5227/api/",
|
||||
baseURL: "https://192.168.1.2:5227/api/",
|
||||
validateStatus: (status) => status < 500,
|
||||
withCredentials: true,
|
||||
headers: { 'Accept': 'application/json' }
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
|
||||
api.interceptors.response.use(response => {
|
||||
|
|
Loading…
Reference in New Issue