Skip to content

Commit

Permalink
implement authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
eaguad1337 committed Oct 25, 2023
1 parent 3f56308 commit 69f15f9
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 14 deletions.
7 changes: 4 additions & 3 deletions src/collapsar/Select.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ def get_display_value(self):
if not (len(self._options) > 0 and isinstance(self._options[0], dict)):
return self.value

if option := next(filter(lambda option: str(option["value"]) == self.value, self._options)):
return option["label"]
filter_value = list(
filter(lambda option: str(option["value"]) == self.value, self._options)
)

return self.value
return filter_value[0]["label"] if filter_value else self.value

def json_serialize(self):
"""
Expand Down
67 changes: 67 additions & 0 deletions src/collapsar/assets/js/components/user-auth-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import * as React from "react"

import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"

interface UserAuthFormProps extends React.HTMLAttributes<HTMLDivElement> {}

export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
const [isLoading, setIsLoading] = React.useState<boolean>(false)

async function onSubmit(event: React.SyntheticEvent) {
event.preventDefault()
setIsLoading(true)

setTimeout(() => {
setIsLoading(false)
}, 3000)
}

return (
<div className={cn("grid gap-6", className)} {...props}>
<form action="/collapsar/auth/login" method="POST">
<div className="grid gap-5">
<div className="grid gap-3">
<Input type="hidden" name="__token" value={window.Collapsar.token} />
<Label htmlFor="email">
Email address
</Label>
<Input
id="email"
name="email"
placeholder=""
type="email"
autoCapitalize="none"
autoComplete="email"
autoCorrect="off"
disabled={isLoading}
/>
</div>
<div className="grid gap-3">
<Label htmlFor="password">
Password
</Label>
<Input
id="password"
name="password"
placeholder=""
type="password"
autoCapitalize="none"
autoComplete="none"
autoCorrect="off"
disabled={isLoading}
/>
</div>
<Button disabled={isLoading}>
{isLoading && (
<Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
)}
Sign In with Email
</Button>
</div>
</form>
</div>
)
}
6 changes: 2 additions & 4 deletions src/collapsar/assets/js/context/CollapsarProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createContext, useEffect, useState } from "react";
import * as Fields from "@/components/fields";
import axios from "axios";

interface renderFormFieldProps {
component: string;
Expand All @@ -8,13 +9,12 @@ interface renderFormFieldProps {
}

interface CollapsarContextProps {
renderFormField: (options: renderFormFieldProps) => JSX.Element;
renderFormField: (options: renderFormFieldProps) => JSX.Element | null;
}

export const CollapsarContext = createContext({} as CollapsarContextProps);

const CollapsarProvider = ({ children }: any) => {

const renderFormField = ({component, field, renderForDisplay = false}: renderFormFieldProps) => {
const FieldComponent = Fields[component as keyof typeof Fields];

Expand All @@ -26,10 +26,8 @@ const CollapsarProvider = ({ children }: any) => {
return (
<FieldComponent renderForDisplay={true} {...field} />
);

}


return (
<CollapsarContext.Provider
value={{
Expand Down
2 changes: 1 addition & 1 deletion src/collapsar/assets/js/pages/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function Layout() {
const outlet = useOutlet();

return (
<ThemeProvider defaultTheme="light" storageKey="vite-ui-theme">
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<CollapsarProvider>
<div className="flex">
<Sidebar />
Expand Down
32 changes: 32 additions & 0 deletions src/collapsar/assets/js/pages/Login.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ThemeProvider } from "@/components/theme-provider";
import { UserAuthForm } from "@/components/user-auth-form";

export function Login() {
return (
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<div className="relative min-h-screen flex flex-col items-center justify-center">
<div className="absolute top-0 left-1 z-20 p-8 flex items-center text-lg font-medium gap-5">
<img
className="w-[50px]"
src="https://avatars.githubusercontent.com/u/148298115?s=200&v=4"
alt=""
/>
Collapsar
</div>

<div className="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
<div className="flex flex-col space-y-2 text-center">
<h1 className="text-2xl font-semibold tracking-tight">Sign in</h1>
<p className="text-sm text-muted-foreground">
{/* Enter your credentials below to continue. */}
</p>
</div>
<UserAuthForm />
<p className="px-8 text-center text-sm text-muted-foreground">

</p>
</div>
</div>
</ThemeProvider>
);
}
5 changes: 5 additions & 0 deletions src/collapsar/assets/js/services/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
} from "react-router-dom";
import { ResourceEdit } from "@/pages/ResourceEdit";
import { ResourceShow } from "@/pages/ResourceShow";
import { Login } from "@/pages/Login";
import axios from "axios";

// use proxy to remount component on resource change
Expand All @@ -16,6 +17,10 @@ const ResourceIndexProxy = (props: any) =>
}

const routes = [
{
path: 'auth/login',
element: <Login />,
},
{
path: '/',
element: <Layout />,
Expand Down
24 changes: 24 additions & 0 deletions src/collapsar/controllers/AuthController.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""A AuthController Module."""
from masonite.controllers import Controller
from masonite.response import Response
from masonite.request import Request
from masonite.authentication import Auth


class AuthController(Controller):
"""AuthController Controller Class."""

def login(self, request: Request, response: Response, auth: Auth):
"""Handle login."""

if (auth.attempt(request.input("email"), request.input("password"))):
return response.redirect('/collapsar/')

return response.redirect('/collapsar/auth/login')

def logout(self, response: Response, auth: Auth):
"""Handle logout."""

auth.logout()

return response.redirect('/collapsar/auth/login')
3 changes: 3 additions & 0 deletions src/collapsar/routes/api.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
from masonite.routes import Route

from ..controllers.ResourceStoreController import ResourceStoreController
from ..controllers.ResourceIndexController import ResourceIndexController
from ..controllers.FieldsController import FieldsController
from ..controllers.ResourceShowController import ResourceShowController
from ..controllers.ResourceUpdateController import ResourceUpdateController
from ..controllers.ResourceDeleteController import ResourceDeleteController


ROUTES = [
Route.group(
[
Expand All @@ -18,5 +20,6 @@
Route.put("/@resource/", ResourceStoreController.handle),
],
prefix="/collapsar-api",
middleware=["auth"]
)
]
7 changes: 6 additions & 1 deletion src/collapsar/routes/web.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
from masonite.routes import Route
from ..controllers.CollapsarController import CollapsarController
from ..controllers.AuthController import AuthController

ROUTES = [
Route.group(
[
Route.get("/auth/login", CollapsarController.index).name('login'),
Route.post("/auth/login", AuthController.login),
Route.get("/auth/logout", AuthController.logout),

Route.get("/assets/app.js", CollapsarController.get_js),
Route.get("/assets/style.css", CollapsarController.get_css),

Route.get('.*', CollapsarController.index)
Route.get('.*', CollapsarController.index).middleware('auth',)
],
prefix="/collapsar",
)
Expand Down
2 changes: 1 addition & 1 deletion src/collapsar/templates/admin/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=1280" />
<meta name="csrf-token" content="{ csrf_token() }" />
<meta name="csrf-token" content="{{ csrf_token }}">

<title>{% block header_title %}{% endblock header_title %}</title>

Expand Down
4 changes: 3 additions & 1 deletion src/collapsar/templates/admin/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
window.Collapsar = {
sidebar: {
items: {{ dashboard_helper.get_resources_navigation() | json_encode() | safe}}
}
},
token: document.head.querySelector('meta[name="csrf-token"]').content,
user: {% if auth.user %} {{ auth.user | json_encode() | safe }} {% else %} {{ "null" }} {% endif %}
}
</script>
{% endblock %}
Expand Down
2 changes: 1 addition & 1 deletion tests/integrations/app/middlewares/VerifyCsrfToken.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
class VerifyCsrfToken(Middleware):

exempt = [
'/collapsar/*',
'/collapsar-api/*',
]
1 change: 0 additions & 1 deletion tests/integrations/app/models/User.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from masoniteorm.scopes import SoftDeletesMixin
from masonite.authentication import Authenticates


class User(Model, SoftDeletesMixin, Authenticates):
"""User Model."""

Expand Down
2 changes: 1 addition & 1 deletion tests/integrations/config/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
AuthenticationProvider,
ValidationProvider,
AuthorizationProvider,
ORMProvider
ORMProvider,
]

PROVIDERS += [CollapsarProvider]

0 comments on commit 69f15f9

Please sign in to comment.