Skip to content

Commit

Permalink
Merge pull request #81 from avored/77-react-admin-template
Browse files Browse the repository at this point in the history
login in react
  • Loading branch information
indpurvesh authored Dec 9, 2023
2 parents dbaed88 + 243b01e commit 5b17f02
Show file tree
Hide file tree
Showing 9 changed files with 417 additions and 139 deletions.
380 changes: 249 additions & 131 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ tokio = { version = "1.32.0", features = ["full"] }
tracing = "0.1.37"
tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
r_i18n = "1.0.1"
tower-http = { version = "0.4.4", features = ["fs"] }
tower-http = { version = "0.4.4", features = ["fs", "cors"] }
dotenvy = "0.15.7"
async-session = "3.0.0"
axum-extra = { version = "0.7.7", features = ["cookie", "cookie-signed"] }
Expand Down
2 changes: 1 addition & 1 deletion react-admin/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
-->
<title>Avored rust content management</title>
</head>
<body>
<body class="antialiased">
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
Expand Down
5 changes: 3 additions & 2 deletions react-admin/src/App.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import './App.css';
import {BrowserRouter, Route, Routes} from 'react-router-dom';
import {BrowserRouter, Navigate, Route, Routes} from 'react-router-dom';
import Dashboard from './pages/Dashboard'
import Login from './pages/auth/Login'

function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/" element={<Navigate to="/admin" replace />} />
<Route path="/admin" element={<Dashboard />} />
<Route path="/admin/login" element={<Login />} />
</Routes>
</BrowserRouter>
Expand Down
16 changes: 16 additions & 0 deletions react-admin/src/assets/logo_only.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 90 additions & 3 deletions react-admin/src/pages/Dashboard.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,98 @@
import logo from '../assets/logo_only.svg'
function Dashboard() {
return (
<div className="flex h-screen w-full justify-center items-center">
<div className="text-indigo-600 text-2xl font-semibold">
Avored rust content management system
<div
className="relative sm:flex sm:justify-center sm:items-center min-h-screen bg-center bg-gray-100 selection:bg-primary-500 selection:text-white">
<div className="max-w-7xl mx-auto p-6 lg:p-8">
<div className="flex justify-center">
<img src={logo} className="w-20 h-20" alt="Avored Rust Cms"/>
</div>

<div className="mt-16">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 lg:gap-8">
<a href="/admin/login"
className="scale-100 p-6 bg-white rounded-lg shadow-2xl shadow-gray-500/20 flex focus:outline focus:outline-2 focus:outline-primary-500">
<div>
<div className="h-16 w-16 bg-primary-50 flex items-center justify-center rounded-full">
<i className="w-7 h-7 stroke-primary-500" data-feather="framer"></i>
</div>

<h2 className="mt-6 text-xl font-semibold text-gray-900">
Administrator
</h2>

<p className="mt-4 text-gray-500 text-sm leading-relaxed">
An app administrator plays a pivotal role in ensuring
the smooth operation of the avored cms.
They are responsible for managing user access,
content updates and overseeing updates. The administrator acts as the
gatekeeper, safeguarding the app's content and user
experience while facilitating its growth and improvement.
In essence, they are the backbone of a well-maintained
and secure avored rust cms ecosystem.
</p>
</div>
<div className="self-center pl-5">
<i className="w-6 h-6 stroke-primary-500" data-feather="chevrons-right"></i>
</div>
</a>

<a href="https://github.com/avored/avored-rust-cms" target="_blank"
className="scale-100 p-6 bg-white rounded-lg shadow-2xl flex focus:outline focus:outline-2 focus:outline-primary-500">
<div>
<div className="h-16 w-16 bg-primary-50 flex items-center justify-center rounded-full">
<i className="w-7 h-7 stroke-primary-500" data-feather="github"></i>
</div>

<h2 className="mt-6 text-xl font-semibold text-gray-900">
Github
</h2>

<p className="mt-4 text-gray-500 text-sm leading-relaxed">
GitHub Star: When you "star" a GitHub repository, it signifies your
interest in that project. Starring a repository
also sends a signal to the repository owner that you
appreciate their work or find it valuable.

Community Help: The GitHub community is known for its collaborative nature.
Developers frequently help each other by contributing to
open-source projects, reporting issues, suggesting improvements,
and even submitting pull requests to fix bugs or add
features. This collective effort is essential for
the growth and success of open-source projects hosted on GitHub.
</p>
</div>

<div className="self-center pl-5">
<i className="w-6 h-6 stroke-primary-500" data-feather="chevrons-right"></i>
</div>
</a>
</div>
</div>

<div className="flex justify-center mt-16 px-0 sm:items-center sm:justify-between">
<div className="text-center text-sm text-gray-500 sm:text-left">
<div className="flex items-center gap-4">
<a href="https://github.com/sponsors/indpurvesh"
className="group inline-flex items-center hover:text-gray-700 dark:hover:text-white focus:outline focus:outline-2 focus:rounded-sm focus:outline-primary-500">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
strokeWidth="1.5"
className="-mt-px mr-1 w-5 h-5 stroke-gray-400 dark:stroke-gray-600 group-hover:stroke-gray-600 dark:group-hover:stroke-gray-400">
<path strokeLinecap="round" strokeLinejoin="round"
d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12z"/>
</svg>
Sponsor
</a>
</div>
</div>

<div className="ml-4 text-center text-sm text-gray-500 sm:text-right sm:ml-0">
AvoRed Rust CMS
</div>
</div>
</div>
</div>
)
}

export default Dashboard
36 changes: 35 additions & 1 deletion react-admin/src/pages/auth/Login.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
import {useState} from "react";
import logo from "../../assets/logo_only.svg";
import {useNavigate} from "react-router-dom";

function Login() {
const [email, setEmail] = useState('[email protected]');
const [password, setPassword] = useState('admin123');
const redirect = useNavigate()
const handleSubmit = (async (e) => {
e.preventDefault()
console.log("handle submit")
const response = (await fetch('http://localhost:8080/api/login', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({email: email, password: password})
}))
const login_response = await response.json()
console.log(login_response)
if (login_response.status) {
localStorage.setItem("AUTH_TOKEN", login_response.data)
return redirect("/admin");
}
})


return (
<div
className="min-h-screen bg-slate-100 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="flex justify-center">
<img src={logo} className="w-20 h-20" alt="Avored Rust Cms"/>
</div>

<div className="sm:mx-auto sm:w-full sm:max-w-md">
<h2 className="mt-6 text-center text-3xl font-extrabold text-gray-900">
Sign into your account
Expand All @@ -13,7 +43,7 @@ function Login() {

<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md">
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<form className="space-y-5" action="/admin/login" method="POST">
<form onSubmit={handleSubmit} className="space-y-5" action="/admin/login" method="POST">
<div>
<label htmlFor="email_address" className="text-sm text-gray-600">
Email Address
Expand All @@ -23,6 +53,8 @@ function Login() {
type="email"
name="email"
required
value={email}
onChange={e => setEmail(e.target.value)}
autoFocus
className="appearance-none rounded-md ring-1 ring-primary-300 relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-primary-500 sm:text-sm focus:z-10"
placeholder="Email Address"
Expand All @@ -38,6 +70,8 @@ function Login() {
type="password"
name="password"
required
value={password}
onChange={e => setPassword(e.target.value)}
className="appearance-none rounded-md ring-1 ring-primary-300 relative block w-full px-3 py-2 border border-gray-300 placeholder-gray-500 text-gray-900 focus:outline-none focus:ring-primary-500 sm:text-sm focus:z-10"
placeholder="Password"
/>
Expand Down
20 changes: 20 additions & 0 deletions src/api/rest_api/rest_api_routes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,32 @@ use std::sync::Arc;

use axum::{routing::get, Router, middleware};
use axum::routing::post;
use axum::http::header::{AUTHORIZATION, CONTENT_TYPE};
use axum::http::header::HeaderValue;
use crate::api::rest_api::handlers::component_all_api_handler::component_all_api_handler;
use crate::api::rest_api::handlers::health_check_api_handler::health_check_api_handler;
use crate::api::rest_api::handlers::admin_user::admin_user_login_api_handler::admin_user_login_api_handler;
use crate::avored_state::AvoRedState;
use crate::middleware::require_jwt_authentication::require_jwt_authentication;
use tower_http::cors::CorsLayer;

pub fn rest_api_routes(state: Arc<AvoRedState>) -> Router {

let backend_url = &state.config.front_end_app_url;

println!("BACKEND URL {backend_url}");
let cors_layer = CorsLayer::new()
.allow_origin(backend_url.parse::<HeaderValue>().unwrap())
.allow_headers([CONTENT_TYPE, AUTHORIZATION])
.allow_methods([
axum::http::Method::GET,
axum::http::Method::POST,
axum::http::Method::PUT,
axum::http::Method::PATCH,
axum::http::Method::DELETE,
axum::http::Method::OPTIONS,
]);

Router::new()
.route("/api/component-all", get(component_all_api_handler))
.route_layer(middleware::from_fn_with_state(
Expand All @@ -18,4 +37,5 @@ pub fn rest_api_routes(state: Arc<AvoRedState>) -> Router {
.route("/api/health-check", get(health_check_api_handler))
.route("/api/login", post(admin_user_login_api_handler))
.with_state(state)
.layer(cors_layer)
}
2 changes: 2 additions & 0 deletions src/providers/avored_config_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub struct AvoRedConfigProvider {
pub database_name: String,
pub session_secret_key: String,
pub jwt_secret_key: String,
pub front_end_app_url: String
}

pub fn config() -> &'static AvoRedConfigProvider {
Expand All @@ -29,6 +30,7 @@ impl AvoRedConfigProvider {
database_name: get_env("AVORED_DATABASE_NAME")?,
session_secret_key: get_env("AVORED_SESSION_SECRET_KEY")?,
jwt_secret_key: get_env("AVORED_JWT_SECRET")?,
front_end_app_url: get_env("AVORED_FRONT_END_APP_URL")?,
})
}
}
Expand Down

0 comments on commit 5b17f02

Please sign in to comment.