implemented permissions

This commit is contained in:
Anton 2023-09-05 16:45:01 +02:00
parent 42fe4fae4e
commit 0138f20b97
15 changed files with 118 additions and 62 deletions

View File

@ -3,7 +3,7 @@ import NavBar from './NavBar'
import { BrowserRouter } from 'react-router-dom' import { BrowserRouter } from 'react-router-dom'
import { ToastContainer } from 'react-toastify' import { ToastContainer } from 'react-toastify'
export function AppShell({ appName, useAuth, children }) { export function AppShell({ appName, children }) {
return ( return (
<BrowserRouter> <BrowserRouter>
<ToastContainer position="top-right" <ToastContainer position="top-right"
@ -16,7 +16,7 @@ export function AppShell({ appName, useAuth, children }) {
draggable draggable
pauseOnHover pauseOnHover
theme="light" /> theme="light" />
<NavBar appName={appName} useAuth={useAuth}></NavBar> <NavBar appName={appName}></NavBar>
<div id="app-content" className="tw-flex tw-!pl-[77px]"> <div id="app-content" className="tw-flex tw-!pl-[77px]">
{children} {children}
</div> </div>

View File

@ -1,6 +1,6 @@
import { useState } from "react"; import { useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
//import { useAuth } from "../api/auth"; import { useAuth } from "../Auth"
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import QuestionMarkIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon' import QuestionMarkIcon from '@heroicons/react/24/outline/QuestionMarkCircleIcon'
@ -8,7 +8,7 @@ import * as React from "react";
import DialogModal from "./DialogModal"; import DialogModal from "./DialogModal";
export default function NavBar({ appName, useAuth }: { appName: string, useAuth: any }) { export default function NavBar({ appName}: { appName: string }) {
const [signupOpen, setSignupOpen] = useState(false); const [signupOpen, setSignupOpen] = useState(false);
@ -110,7 +110,7 @@ export default function NavBar({ appName, useAuth }: { appName: string, useAuth:
{isAuthenticated ? {isAuthenticated ?
<div className="tw-flex-none"> <div className="tw-flex-none">
{user.avatar ? <div className="tw-avatar"> {user?.avatar ? <div className="tw-avatar">
<div className="tw-w-10 tw-rounded-full"> <div className="tw-w-10 tw-rounded-full">
<img src={"https://api.utopia-lab.org/assets/" + user?.avatar + "?access_token=" + token} /> <img src={"https://api.utopia-lab.org/assets/" + user?.avatar + "?access_token=" + token} />
</div> </div>
@ -122,7 +122,7 @@ export default function NavBar({ appName, useAuth }: { appName: string, useAuth:
<path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" /> <path d="M10 6a2 2 0 110-4 2 2 0 010 4zM10 12a2 2 0 110-4 2 2 0 010 4zM10 18a2 2 0 110-4 2 2 0 010 4z" />
</svg> </svg>
</label> </label>
<ul tabIndex={0} className="tw-menu tw-menu-compact tw-dropdown-content tw-mt-3 tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-w-52 !tw-z-[1500]"> <ul tabIndex={0} className="tw-menu tw-menu-compact tw-dropdown-content tw-mt-3 tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-w-52 !tw-z-[10000]">
<li><Link to={"/settings"}>Settings</Link></li> <li><Link to={"/settings"}>Settings</Link></li>
<li><a onClick={() => { onLogout() }}>Logout</a></li> <li><a onClick={() => { onLogout() }}>Logout</a></li>
</ul> </ul>
@ -148,7 +148,7 @@ export default function NavBar({ appName, useAuth }: { appName: string, useAuth:
</label> </label>
<ul tabIndex={1} className="tw-menu tw-dropdown-content tw-mt-3 tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-w-52 !tw-z-[1500]"> <ul tabIndex={1} className="tw-menu tw-dropdown-content tw-mt-3 tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box tw-w-52 !tw-z-[10000]">
<li><a onClick={() => {setLoginOpen(true)}}>Login</a></li> <li><a onClick={() => {setLoginOpen(true)}}>Login</a></li>
<li><a onClick={() => setSignupOpen(true)}>Sign Up</a></li> <li><a onClick={() => setSignupOpen(true)}>Sign Up</a></li>
</ul> </ul>

View File

@ -1,4 +1,4 @@
import {useState, useRef} from 'react' import {useState} from 'react'
import {Link} from 'react-router-dom' import {Link} from 'react-router-dom'
import ErrorText from '../Typography/ErrorText' import ErrorText from '../Typography/ErrorText'
import {TextInput} from '../Input/TextInput' import {TextInput} from '../Input/TextInput'

View File

@ -1,4 +1,4 @@
import { useState, useRef } from 'react' import { useState } from 'react'
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import ErrorText from '../Typography/ErrorText' import ErrorText from '../Typography/ErrorText'
import {TextInput} from '../Input/TextInput' import {TextInput} from '../Input/TextInput'

View File

@ -22,7 +22,7 @@ type AuthContextProps = {
login: (credentials: AuthCredentials) => Promise<UserItem | undefined>, login: (credentials: AuthCredentials) => Promise<UserItem | undefined>,
register: (credentials: AuthCredentials, userName: string) => Promise<UserItem | undefined>, register: (credentials: AuthCredentials, userName: string) => Promise<UserItem | undefined>,
loading: Boolean, loading: Boolean,
logout: () => void, logout: () => Promise<any>,
updateUser: (user: UserItem) => any, updateUser: (user: UserItem) => any,
token: String | null token: String | null
} }
@ -33,7 +33,7 @@ const AuthContext = createContext<AuthContextProps>({
login: () => Promise.reject(), login: () => Promise.reject(),
register: () => Promise.reject(), register: () => Promise.reject(),
loading: false, loading: false,
logout: () => { }, logout: () => Promise.reject(),
updateUser: () => Promise.reject(), updateUser: () => Promise.reject(),
token: "" token: ""
}); });

View File

@ -23,7 +23,6 @@ export const Layer = (props: LayerProps) => {
const searchPhrase = useSearchPhrase(); const searchPhrase = useSearchPhrase();
useEffect(() => { useEffect(() => {
resetItems(props); resetItems(props);
props.data && setItemsData(props); props.data && setItemsData(props);

View File

@ -1,16 +1,22 @@
import * as React from 'react' import * as React from 'react'
import { useEffect } from 'react'; import { useEffect } from 'react';
import { ItemsApi, Permission } from '../../types'; import { ItemsApi, Permission } from '../../types';
import { useSetPermissionData, useSetPermissionApi } from './hooks/usePermissions' import { useSetPermissionData, useSetPermissionApi, useSetAdminRole } from './hooks/usePermissions'
import { useAuth } from '../Auth';
export function Permissions({data, api} : {data?: Permission[], api?: ItemsApi<Permission>}) { export function Permissions({data, api, adminRole} : {data?: Permission[], api?: ItemsApi<Permission>, adminRole?: string}) {
const setPermissionData = useSetPermissionData(); const setPermissionData = useSetPermissionData();
const setPermissionApi = useSetPermissionApi(); const setPermissionApi = useSetPermissionApi();
const setAdminRole = useSetAdminRole();
const {user} = useAuth();
useEffect(() => { useEffect(() => {
console.log(adminRole);
adminRole && setAdminRole(adminRole);
data && setPermissionData(data); data && setPermissionData(data);
api && setPermissionApi(api); api && setPermissionApi(api);
}, [api, data]) }, [api, data, adminRole, user])
return ( return (
<></> <></>

View File

@ -1,11 +1,14 @@
import * as React from 'react' import * as React from 'react'
import DynamicHeroIcon from '../../../Utils/DynamicHeroIcon' import DynamicHeroIcon from '../../../Utils/DynamicHeroIcon'
import { useLayers } from '../hooks/useLayers' import { useLayers } from '../hooks/useLayers'
import { useHasUserPermission } from '../hooks/usePermissions';
export default function AddButton({ setSelectNewItemPosition }: { setSelectNewItemPosition: React.Dispatch<React.SetStateAction<any>> }) { export default function AddButton({ setSelectNewItemPosition }: { setSelectNewItemPosition: React.Dispatch<React.SetStateAction<any>> }) {
const layers = useLayers(); const layers = useLayers();
const hasUserPermission = useHasUserPermission();
return ( return (
<div className="tw-dropdown tw-dropdown-top tw-dropdown-end tw-dropdown-hover tw-z-500 tw-absolute tw-right-5 tw-bottom-5" > <div className="tw-dropdown tw-dropdown-top tw-dropdown-end tw-dropdown-hover tw-z-500 tw-absolute tw-right-5 tw-bottom-5" >
@ -16,7 +19,7 @@ export default function AddButton({ setSelectNewItemPosition }: { setSelectNewIt
</label> </label>
<ul tabIndex={0} className="tw-dropdown-content tw-pr-1 tw-list-none"> <ul tabIndex={0} className="tw-dropdown-content tw-pr-1 tw-list-none">
{layers.map((layer) => ( {layers.map((layer) => (
layer.api?.createItem && ( layer.api?.createItem && hasUserPermission(layer.api.collectionName!,"create") && (
<li key={layer.name} > <li key={layer.name} >
<a> <a>
<div className="tw-tooltip tw-tooltip-left" data-tip={layer.menuText}> <div className="tw-tooltip tw-tooltip-left" data-tip={layer.menuText}>

View File

@ -5,6 +5,7 @@ import { ItemFormPopupProps } from "../ItemFormPopup";
import { LatLng } from "leaflet"; import { LatLng } from "leaflet";
import { Item } from "../../../../types"; import { Item } from "../../../../types";
import { toast } from "react-toastify"; import { toast } from "react-toastify";
import { useHasUserPermission, usePermissions } from "../../hooks/usePermissions";
@ -17,12 +18,15 @@ export function HeaderView({ item, setItemFormPopup }: {
const removeItem = useRemoveItem(); const removeItem = useRemoveItem();
const map = useMap(); const map = useMap();
const hasUserPermission = useHasUserPermission();
const permissions = usePermissions();
const removeItemFromMap = async (event: React.MouseEvent<HTMLElement>) => { const removeItemFromMap = async (event: React.MouseEvent<HTMLElement>) => {
setLoading(true); setLoading(true);
let success = false; let success = false;
try { try {
await item.layer.api?.deleteItem!(item.id) await item.layer?.api?.deleteItem!(item.id)
success = true; success = true;
} catch (error) { } catch (error) {
toast.error(error.toString()); toast.error(error.toString());
@ -41,16 +45,22 @@ export function HeaderView({ item, setItemFormPopup }: {
event.stopPropagation(); event.stopPropagation();
map.closePopup(); map.closePopup();
if (setItemFormPopup) if (setItemFormPopup)
setItemFormPopup({ position: new LatLng(item.position.coordinates[1], item.position.coordinates[0]), layer: item.layer, item: item, setItemFormPopup: setItemFormPopup }) setItemFormPopup({ position: new LatLng(item.position.coordinates[1], item.position.coordinates[0]), layer: item.layer!, item: item, setItemFormPopup: setItemFormPopup })
} }
console.log(item.layer.api.collectionName);
console.log(permissions);
console.log( hasUserPermission(item.api?.collectionName!,"update") );
return ( return (
<div className='tw-grid tw-grid-cols-6 tw-pb-2'> <div className='tw-grid tw-grid-cols-6 tw-pb-2'>
<div className='tw-col-span-5'> <div className='tw-col-span-5'>
<b className="tw-text-xl tw-font-bold">{item.name}</b> <b className="tw-text-xl tw-font-bold">{item.name}</b>
</div> </div>
<div className='tw-col-span-1'> <div className='tw-col-span-1'>
{item.layer.api && {item.layer?.api &&
<div className="tw-dropdown tw-dropdown-bottom"> <div className="tw-dropdown tw-dropdown-bottom">
<label tabIndex={0} className="tw-bg-base-100 tw-btn tw-m-1 tw-leading-3 tw-border-none tw-min-h-0 tw-h-6"> <label tabIndex={0} className="tw-bg-base-100 tw-btn tw-m-1 tw-leading-3 tw-border-none tw-min-h-0 tw-h-6">
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
@ -58,7 +68,7 @@ export function HeaderView({ item, setItemFormPopup }: {
</svg> </svg>
</label> </label>
<ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box"> <ul tabIndex={0} className="tw-dropdown-content tw-menu tw-p-2 tw-shadow tw-bg-base-100 tw-rounded-box">
{item.layer.api.updateItem && <li> {item.layer.api.updateItem && hasUserPermission(item.layer.api?.collectionName!,"update") && <li>
<a className="!tw-text-base-content" onClick={openEditPopup}> <a className="!tw-text-base-content" onClick={openEditPopup}>
<svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor"> <svg xmlns="http://www.w3.org/2000/svg" className="tw-h-5 tw-w-5" viewBox="0 0 20 20" fill="currentColor">
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" /> <path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
@ -66,7 +76,7 @@ export function HeaderView({ item, setItemFormPopup }: {
</a> </a>
</li>} </li>}
{item.layer.api.deleteItem && <li> {item.layer.api.deleteItem && hasUserPermission(item.layer.api?.collectionName!,"delete") && <li>
<a className=' !tw-text-error' onClick={removeItemFromMap}> <a className=' !tw-text-error' onClick={removeItemFromMap}>
{loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span> {loading ? <span className="tw-loading tw-loading-spinner tw-loading-sm"></span>
: :

View File

@ -13,6 +13,7 @@ import { TagsProvider } from "./hooks/useTags";
import { LayersProvider } from "./hooks/useLayers"; import { LayersProvider } from "./hooks/useLayers";
import { FilterProvider } from "./hooks/useFilter"; import { FilterProvider } from "./hooks/useFilter";
import { FilterControl } from "./Subcomponents/FilterControl"; import { FilterControl } from "./Subcomponents/FilterControl";
import { PermissionsProvider } from "./hooks/usePermissions";
export interface MapEventListenerProps { export interface MapEventListenerProps {
@ -57,37 +58,39 @@ function UtopiaMap({
return ( return (
<LayersProvider initialLayers={[]}> <LayersProvider initialLayers={[]}>
<TagsProvider initialTags={[]}> <TagsProvider initialTags={[]}>
<FilterProvider initialTags={[]}> <PermissionsProvider initialPermissions={[]}>
<ItemsProvider initialItems={[]}> <FilterProvider initialTags={[]}>
<div className={(selectNewItemPosition != null ? "crosshair-cursor-enabled" : undefined)}> <ItemsProvider initialItems={[]}>
<MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={center} zoom={zoom} zoomControl={false}> <div className={(selectNewItemPosition != null ? "crosshair-cursor-enabled" : undefined)}>
<FilterControl></FilterControl> <MapContainer ref={mapDivRef} style={{ height: height, width: width }} center={center} zoom={zoom} zoomControl={false}>
<TileLayer <FilterControl></FilterControl>
attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' <TileLayer
url="https://tile.osmand.net/hd/{z}/{x}/{y}.png" /> attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
<MarkerClusterGroup showCoverageOnHover chunkedLoading maxClusterRadius={50} removeOutsideVisibleBounds={false}> url="https://tile.osmand.net/hd/{z}/{x}/{y}.png" />
{ <MarkerClusterGroup showCoverageOnHover chunkedLoading maxClusterRadius={50} removeOutsideVisibleBounds={false}>
React.Children.toArray(children).map((child) => {
React.isValidElement<{ setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps>>, itemFormPopup: ItemFormPopupProps | null }>(child) ? React.Children.toArray(children).map((child) =>
React.cloneElement(child, { setItemFormPopup: setItemFormPopup, itemFormPopup: itemFormPopup }) : child React.isValidElement<{ setItemFormPopup: React.Dispatch<React.SetStateAction<ItemFormPopupProps>>, itemFormPopup: ItemFormPopupProps | null }>(child) ?
) React.cloneElement(child, { setItemFormPopup: setItemFormPopup, itemFormPopup: itemFormPopup }) : child
} )
</MarkerClusterGroup> }
<MapEventListener setSelectNewItemPosition={setSelectNewItemPosition} selectNewItemPosition={selectNewItemPosition} setItemFormPopup={setItemFormPopup} /> </MarkerClusterGroup>
</MapContainer> <MapEventListener setSelectNewItemPosition={setSelectNewItemPosition} selectNewItemPosition={selectNewItemPosition} setItemFormPopup={setItemFormPopup} />
<AddButton setSelectNewItemPosition={setSelectNewItemPosition}></AddButton> </MapContainer>
{selectNewItemPosition != null && <AddButton setSelectNewItemPosition={setSelectNewItemPosition}></AddButton>
<div className="tw-button tw-z-1000 tw-absolute tw-right-5 tw-top-4 tw-drop-shadow-md"> {selectNewItemPosition != null &&
<div className="tw-alert tw-bg-base-100 tw-text-base-content"> <div className="tw-button tw-z-1000 tw-absolute tw-right-5 tw-top-4 tw-drop-shadow-md">
<div> <div className="tw-alert tw-bg-base-100 tw-text-base-content">
<span>Select {selectNewItemPosition.name} position!</span> <div>
<span>Select {selectNewItemPosition.name} position!</span>
</div>
</div> </div>
</div> </div>
</div> }
} </div>
</div> </ItemsProvider>
</ItemsProvider> </FilterProvider>
</FilterProvider> </PermissionsProvider>
</TagsProvider> </TagsProvider>
</LayersProvider> </LayersProvider>
); );

View File

@ -1,6 +1,7 @@
import { useCallback, useReducer, createContext, useContext } from "react"; import { useCallback, useReducer, createContext, useContext } from "react";
import * as React from "react"; import * as React from "react";
import { ItemsApi, Permission } from "../../../types"; import { ItemsApi, LayerProps, Permission, PermissionAction } from "../../../types";
import { useAuth } from "../../Auth";
type ActionType = type ActionType =
| { type: "ADD"; permission: Permission } | { type: "ADD"; permission: Permission }
@ -11,13 +12,17 @@ type UsePermissionManagerResult = ReturnType<typeof usePermissionsManager>;
const PermissionContext = createContext<UsePermissionManagerResult>({ const PermissionContext = createContext<UsePermissionManagerResult>({
permissions: [], permissions: [],
setPermissionApi: () => { }, setPermissionApi: () => { },
setPermissionData: () => { } setPermissionData: () => { },
setAdminRole: () => { },
hasUserPermission: () => true
}); });
function usePermissionsManager(initialPermissions: Permission[]): { function usePermissionsManager(initialPermissions: Permission[]): {
permissions: Permission[]; permissions: Permission[];
setPermissionApi: (api: ItemsApi<Permission>) => void; setPermissionApi: (api: ItemsApi<any>) => void;
setPermissionData: (data: Permission[]) => void; setPermissionData: (data: Permission[]) => void;
setAdminRole: (adminRole: string) => void;
hasUserPermission: (collectionName: string, action: PermissionAction) => boolean;
} { } {
const [permissions, dispatch] = useReducer((state: Permission[], action: ActionType) => { const [permissions, dispatch] = useReducer((state: Permission[], action: ActionType) => {
switch (action.type) { switch (action.type) {
@ -38,10 +43,13 @@ function usePermissionsManager(initialPermissions: Permission[]): {
} }
}, initialPermissions); }, initialPermissions);
const [api, setApi] = React.useState<ItemsApi<Permission>>({} as ItemsApi<Permission>) const [adminRole, setAdminRole] = React.useState<string | null>(null);
const { user } = useAuth();
const setPermissionApi = useCallback(async (api: ItemsApi<Permission>) => { const setPermissionApi = useCallback(async (api: ItemsApi<Permission>) => {
setApi(api); console.log("check");
const result = await api.getItems(); const result = await api.getItems();
if (result) { if (result) {
result.map(permission => { result.map(permission => {
@ -56,8 +64,17 @@ function usePermissionsManager(initialPermissions: Permission[]): {
}) })
}, []); }, []);
const hasUserPermission = useCallback((collectionName: string, action: PermissionAction) => {
console.log(permissions);
if (permissions.length == 0) return true;
else if (user && user.role == adminRole) return true;
else return permissions.some(p => p.action === action && p.collection === collectionName && p.role == user?.role)
}, [permissions, user]);
return { permissions, setPermissionApi, setPermissionData };
return { permissions, setPermissionApi, setPermissionData, setAdminRole, hasUserPermission };
} }
export const PermissionsProvider: React.FunctionComponent<{ export const PermissionsProvider: React.FunctionComponent<{
@ -82,4 +99,14 @@ export const useSetPermissionApi = (): UsePermissionManagerResult["setPermission
export const useSetPermissionData = (): UsePermissionManagerResult["setPermissionData"] => { export const useSetPermissionData = (): UsePermissionManagerResult["setPermissionData"] => {
const { setPermissionData } = useContext(PermissionContext); const { setPermissionData } = useContext(PermissionContext);
return setPermissionData; return setPermissionData;
}
export const useHasUserPermission = (): UsePermissionManagerResult["hasUserPermission"] => {
const { hasUserPermission } = useContext(PermissionContext);
return hasUserPermission;
}
export const useSetAdminRole = (): UsePermissionManagerResult["setAdminRole"] => {
const { setAdminRole } = useContext(PermissionContext);
return setAdminRole;
} }

View File

@ -1,6 +1,7 @@
export { UtopiaMap } from './UtopiaMap'; export { UtopiaMap } from './UtopiaMap';
export { Layer } from './Layer'; export { Layer } from './Layer';
export { Tags } from "./Tags"; export { Tags } from "./Tags";
export { Permissions } from "./Permissions";
export {ItemForm} from './ItemForm'; export {ItemForm} from './ItemForm';
export {ItemView} from './ItemView'; export {ItemView} from './ItemView';
export {PopupTextAreaInput} from './Subcomponents/ItemPopupComponents/PopupTextAreaInput'; export {PopupTextAreaInput} from './Subcomponents/ItemPopupComponents/PopupTextAreaInput';

View File

@ -4,11 +4,13 @@ import {TextInput} from '../Input/TextInput'
import {TextAreaInput} from '../Input/TextAreaInput' import {TextAreaInput} from '../Input/TextAreaInput'
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import {useNavigate} from 'react-router-dom' import {useNavigate} from 'react-router-dom'
import { useAuth } from '../Auth';
import * as React from 'react' import * as React from 'react'
import 'react-toastify/dist/ReactToastify.css'; import 'react-toastify/dist/ReactToastify.css';
import { UserItem } from '../../types';
export function Settings({useAuth}) { export function Settings() {
const { user, updateUser, loading } = useAuth(); const { user, updateUser, loading } = useAuth();
@ -35,7 +37,7 @@ export function Settings({useAuth}) {
const onUpdateUser = () => { const onUpdateUser = () => {
let changedUser = {}; let changedUser = {} as UserItem;
if(passwordChanged) { if(passwordChanged) {
changedUser = { id: id, first_name: name, description: text, email: email, password: password }; changedUser = { id: id, first_name: name, description: text, email: email, password: password };

View File

@ -1,4 +1,4 @@
export { UtopiaMap, Layer, Tags, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, TextView, StartEndView } from './Components/Map/index'; export { UtopiaMap, Layer, Tags, Permissions, ItemForm, ItemView, PopupTextAreaInput, PopupStartEndInput, TextView, StartEndView } from './Components/Map';
export {AppShell, Content, SideBar} from "./Components/AppShell" export {AppShell, Content, SideBar} from "./Components/AppShell"
export {AuthProvider, useAuth, LoginPage, SignupPage} from "./Components/Auth" export {AuthProvider, useAuth, LoginPage, SignupPage} from "./Components/Auth"
export {Settings} from './Components/Profile' export {Settings} from './Components/Profile'

View File

@ -66,6 +66,7 @@ export interface ItemsApi<T> {
createItem?(item : T): Promise<any>, createItem?(item : T): Promise<any>,
updateItem?(item : T): Promise<any>, updateItem?(item : T): Promise<any>,
deleteItem?(id : number | string): Promise<any>, deleteItem?(id : number | string): Promise<any>,
collectionName?: string
} }
export interface UserApi { export interface UserApi {
@ -79,7 +80,8 @@ export interface UserApi {
export type UserItem = { export type UserItem = {
id?: string; id?: string;
avatar: string; avatar?: string;
role?: string;
first_name: string; first_name: string;
description: string; description: string;
email: string; email: string;
@ -90,5 +92,8 @@ export type Permission = {
id?: string; id?: string;
role: string; role: string;
collection: string; collection: string;
action: string; action: PermissionAction
} }
export type PermissionAction = "create"|"read"|"update"|"delete";