diff --git a/SafeCity/ClientApp/src/index.tsx b/SafeCity/ClientApp/src/index.tsx index d56bac5..fbf20ae 100644 --- a/SafeCity/ClientApp/src/index.tsx +++ b/SafeCity/ClientApp/src/index.tsx @@ -3,8 +3,15 @@ import ReactDOM from 'react-dom'; import { BrowserRouter } from 'react-router-dom'; import './index.css'; import App from './App'; +import auth from './services/auth'; import * as serviceWorker from './serviceWorker'; +auth.load(updateSigninStatus); + +function updateSigninStatus(isSignedIn: boolean) { + console.log(`app loaded, signed in: ${isSignedIn} token: ${auth.getToken()}`); +} + const rootElement = document.getElementById('root'); ReactDOM.render( diff --git a/SafeCity/ClientApp/src/pages/Layout.tsx b/SafeCity/ClientApp/src/pages/Layout.tsx index 36a3761..0a40d20 100644 --- a/SafeCity/ClientApp/src/pages/Layout.tsx +++ b/SafeCity/ClientApp/src/pages/Layout.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { NavLink } from 'react-router-dom'; import Navbar from 'react-bootstrap/Navbar'; import Nav from 'react-bootstrap/Nav'; +import auth from '../services/auth'; function Layout(props: any) { return ( @@ -24,6 +25,9 @@ function Layout(props: any) {
  • Про нас
  • +
  • + +
  • diff --git a/SafeCity/ClientApp/src/services/auth.ts b/SafeCity/ClientApp/src/services/auth.ts new file mode 100644 index 0000000..ada7b88 --- /dev/null +++ b/SafeCity/ClientApp/src/services/auth.ts @@ -0,0 +1,49 @@ +const CLIENT_ID = '674253053711-5kesmhgnisu9hukdgf7l6v8k9scs85s8.apps.googleusercontent.com'; + +declare global { + interface Window { + gapi: any; + } +} + +function loadScript(callback: any) { + const script = document.createElement('script'); + + script.src = `https://apis.google.com/js/api.js`; + script.async = true; + + document.head.appendChild(script); + script.onload = callback +}; + +function getToken() { + return window.gapi ? window.gapi.auth2.getAuthInstance().currentUser.get().getAuthResponse().id_token : undefined; +}; + +function signIn() { + window.gapi.auth2.getAuthInstance().signIn() + .then(() => console.log('signed in')); +}; + +function signOut() { + window.gapi.auth2.getAuthInstance().signOut() + .then(() => console.log('User signed out.')); +}; + +export default { + load: (updateSigninStatus: Function) => loadScript(() => { + window.gapi.load('auth2', () => { + window.gapi.auth2.init({ + clientId: CLIENT_ID, + }).then(() => { + window.gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus); + updateSigninStatus(window.gapi.auth2.getAuthInstance().isSignedIn.get()); + }, (error: any) => { + console.log('failed to initialize google API client ', error); + }); + }); + }), + getToken: getToken, + signIn:signIn, + signOut:signOut, +} \ No newline at end of file diff --git a/SafeCity/ClientApp/src/services/crud.ts b/SafeCity/ClientApp/src/services/crud.ts index 94c3845..7e349a6 100644 --- a/SafeCity/ClientApp/src/services/crud.ts +++ b/SafeCity/ClientApp/src/services/crud.ts @@ -1,12 +1,15 @@ +import auth from './auth'; -export async function get(url:string) { - const idToken = 'dummy_token'; - const options = { - method: 'GET', - headers: { - 'Authorization': `Bearer ${idToken}`, - }, - }; +enum Method { + GET = 'GET', + POST = 'POST', + PUT = 'PUT', + DELETE = 'DELETE', +} + +export async function get(url: string) { + const options = getOptions(Method.GET); + return new Promise((resolve, reject) => { fetch(url, options) .then(res => { @@ -24,21 +27,16 @@ export async function get(url:string) { }; export async function post(url:string, entity:any) { - return await action(url, 'POST', entity); + return await action(url, Method.POST, entity); }; export async function put(url:string, entity:any) { - return await action(url, 'PUT', entity); + return await action(url, Method.PUT, entity); }; export async function del(url:string) { - const idToken = 'dummy_token'; - const options = { - headers: { - 'Authorization': `Bearer ${idToken}`, - }, - method: 'DELETE', - }; + const options = getOptions(Method.DELETE); + return new Promise((resolve, reject) => { fetch(url, options) .then(res => { @@ -51,17 +49,29 @@ export async function del(url:string) { }); }; -async function action(url:string, method:string, entity:any) { - const idToken = 'dummy_token'; +function getOptions(method:Method, entity:any|undefined = undefined): RequestInit{ + const idToken = auth.getToken(); + const options = { - method: method, - headers: { + method, + } as RequestInit; + + if(idToken){ + options.headers = { 'Authorization': `Bearer ${idToken}`, 'Accept': 'application/json', 'Content-Type': 'application/json' - }, - body: JSON.stringify(entity), - }; + }; + } + if(entity){ + options.body = JSON.stringify(entity); + } + + return options; +}; + +async function action(url:string, method:Method, entity:any) { + const options = getOptions(method, entity); return new Promise((resolve, reject) => { fetch(url, options) diff --git a/SafeCity/Controllers/ProjectsController.cs b/SafeCity/Controllers/ProjectsController.cs index dca53e4..8ec384c 100644 --- a/SafeCity/Controllers/ProjectsController.cs +++ b/SafeCity/Controllers/ProjectsController.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; using AutoMapper; using SafeCity.DTOs; diff --git a/SafeCity/SafeCity.csproj b/SafeCity/SafeCity.csproj index 443f35a..7dd1ea1 100644 --- a/SafeCity/SafeCity.csproj +++ b/SafeCity/SafeCity.csproj @@ -11,6 +11,8 @@ + + diff --git a/SafeCity/Startup.cs b/SafeCity/Startup.cs index 537a32c..f06968e 100644 --- a/SafeCity/Startup.cs +++ b/SafeCity/Startup.cs @@ -1,7 +1,7 @@ using AutoMapper; +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; @@ -25,23 +25,12 @@ public Startup(IConfiguration configuration) // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { - services.AddMvc(p => - { - p.EnableEndpointRouting = false; - }); + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(jwt => jwt.UseGoogle( + clientId: Configuration["Authentication:Google:ClientId"])); - services.AddControllersWithViews(); services.AddControllers().AddNewtonsoftJson(); - services.AddDbContext( - opt => opt.UseNpgsql(Configuration["ConnectionStrings:SafeCityConnectionString"])); - - // In production, the React files will be served from this directory - services.AddSpaStaticFiles(configuration => - { - configuration.RootPath = "ClientApp/build"; - }); - services.AddHttpContextAccessor(); services.AddScoped(); @@ -51,6 +40,20 @@ public void ConfigureServices(IServiceCollection services) new LiqPayService(Configuration["LiqPay:PublicKey"], Configuration["LiqPay:PrivateKey"])); services.AddAutoMapper(typeof(Startup).Assembly); + + services.AddMvc(p => + { + p.EnableEndpointRouting = false; + }); + + services.AddDbContext( + opt => opt.UseNpgsql(Configuration["ConnectionStrings:SafeCityConnectionString"])); + + // In production, the React files will be served from this directory + services.AddSpaStaticFiles(configuration => + { + configuration.RootPath = "ClientApp/build"; + }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -67,20 +70,16 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseHsts(); } - app.UseMvc(); - + //app.UseMvc(); app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseSpaStaticFiles(); - app.UseRouting(); + //app.UseRouting(); - app.UseEndpoints(endpoints => - { - endpoints.MapControllerRoute( - name: "default", - pattern: "{controller}/{action=Index}/{id?}"); - }); + app.UseAuthentication(); + + app.UseMvcWithDefaultRoute(); app.UseSpa(spa => { diff --git a/SafeCity/appsettings.Development.json b/SafeCity/appsettings.Development.json index 126a2e5..8b268e6 100644 --- a/SafeCity/appsettings.Development.json +++ b/SafeCity/appsettings.Development.json @@ -12,5 +12,10 @@ "LiqPay": { "PublicKey": "sandbox_i98303515576", "PrivateKey": "sandbox_fXB33L5nU5kWoNJC1bh26Z3h3ZVU2flGfci3hhDs" - } + }, + "Authentication": { + "Google": { + "ClientId": "674253053711-5kesmhgnisu9hukdgf7l6v8k9scs85s8.apps.googleusercontent.com" + } + } } \ No newline at end of file