Skip to content

Commit

Permalink
Moderator (#88)
Browse files Browse the repository at this point in the history
* remove obsolete files
* made Login as configurable component
* externalize auth
* moderator
  • Loading branch information
sebastianovide committed Nov 9, 2018
1 parent 86d2e4f commit 18cdc12
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 38 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
- login
- recognize moderator
- introducing configurable components
- get user groups
- moderator user

## 0.2.2 (2018-11-05)
- fix map iOS
Expand Down
14 changes: 14 additions & 0 deletions firestore.rules
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
service cloud.firestore {
match /databases/{database}/documents {

function isAdmin() {
return get(/databases/$(database)/documents/users/$(request.auth.uid)).data.isAdmin == true
}

function isOwner(uid) {
return request.auth.uid == uid
}

// anybody can read the photos but only admin can write
match /photos/{photo} {
allow read: if true;
Expand All @@ -9,6 +17,12 @@ service cloud.firestore {
allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
}

// data written by admin
match /users/{uid} {
allow read: if isAdmin() || isOwner(uid);
allow write: if isAdmin();
}

// only logged in users can add
// owners can update
// admin can do anything
Expand Down
4 changes: 2 additions & 2 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import PhotoPage from './Components/PhotoPage';
import LandingPage from './Components/LandingPage';
import Map from './Components/Map';
import Loading from './Components/Loading';
import Db from './services/Db.js';
import config from "./services/config";

class App extends Component {
constructor(props){
Expand Down Expand Up @@ -92,7 +92,7 @@ class App extends Component {
componentDidMount(){
this.getLocation();

this.unregisterAuthObserver = Db.onAuthStateChanged((user) => {
this.unregisterAuthObserver = config.authModule.onAuthStateChanged((user) => {
this.setState({isSignedIn: !!user});
});
}
Expand Down
10 changes: 6 additions & 4 deletions src/Components/LandingPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import MenuItem from '@material-ui/core/MenuItem';
import MenuList from '@material-ui/core/MenuList';
import CustomPhotoDialog from './CustomPhotoDialog';

import Db from '../services/Db';
import config from '../services/config';
import './LandingPage.scss';
import Login from './Login';
Expand Down Expand Up @@ -75,7 +74,7 @@ class LandingPage extends Component {
let loginLogoutDialogOpen = true;

if (this.props.isSignedIn) {
Db.signOut();
config.authModule.signOut();
loginLogoutDialogOpen = false;
}

Expand Down Expand Up @@ -154,7 +153,10 @@ class LandingPage extends Component {
<MenuItem onClick={this.openPage1}>Page 1</MenuItem>
<MenuItem onClick={this.openPage2}>Page 2</MenuItem>
<MenuItem onClick={this.openPage3}>Page 3</MenuItem>
<MenuItem onClick={this.handleClickLoginLogout}>{this.props.isSignedIn ? "Sign Out " + Db.currentUser().displayName : "Sign In"}</MenuItem>
<MenuItem onClick={this.handleClickLoginLogout}>{this.props.isSignedIn ? "Sign Out " + config.authModule.getCurrentUser().isModerator + " " + config.authModule.getCurrentUser().displayName : "Sign In"}</MenuItem>
{config.authModule.getCurrentUser().isModerator ?
<MenuItem onClick={this.openPage1}>{"Moderator"}</MenuItem> : null}

</MenuList>
</ClickAwayListener>
</Paper>
Expand Down Expand Up @@ -187,7 +189,7 @@ class LandingPage extends Component {
<Login
open={this.state.loginLogoutDialogOpen && this.props.isSignedIn !== undefined && !this.state.isSignedIn}
handleClose={this.handleLoginClose}
loginName={config.loginComponentName}
loginComponent={config.loginComponent}
/>

</div>
Expand Down
8 changes: 3 additions & 5 deletions src/Components/Login.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@ class Login extends React.Component {
this.state = {
open: false
};

this.Component = require("../services/" + this.props.loginName + ".js").default;
}
}

handleClose = () => {
this.props.handleClose();
return true;
};

render() {
const Component = this.Component;
const Component = this.props.loginComponent;
return (
<Component key={this.props.loginName} {...this.props}/>
<Component key={""} {...this.props}/>
);
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Components/Map.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
import Button from '@material-ui/core/Button';
import backButton from '../images/left-arrow.svg';
import Db from '../services/Db.js';
import './Map.scss';
import config from "../services/config";

const CENTER = [-0.1019313, 51.524311];
const ZOOM = 10;
Expand All @@ -21,7 +21,7 @@ class Map extends Component {
};

async componentDidMount(){
const photos = Db.fetchPhotos();
const photos = config.dbModule.fetchPhotos();

mapboxgl.accessToken = ''; // you can add a Mapbox access token here
this.map = new mapboxgl.Map({
Expand Down
2 changes: 1 addition & 1 deletion src/services/LoginFirebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import DialogContent from '@material-ui/core/DialogContent';
import DialogTitle from '@material-ui/core/DialogTitle';
import withMobileDialog from '@material-ui/core/withMobileDialog'

import {firebaseApp} from './firebaseInit.js';
import firebaseApp from './firebaseInit.js';
import firebase from 'firebase/app';

import 'firebase/auth';
Expand Down
31 changes: 31 additions & 0 deletions src/services/authFirebase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import User from "../types/User";
import firebaseApp from "./firebaseInit";
import dbFirebase from "./dbFirebase";

let currentUser;

/**
* When the user login call fn
* @param fn
*/
const onAuthStateChanged = async (fn) => {
const firebaseStatusChange = async (user) => {
currentUser = user;
if (currentUser) {
const fbUser = await dbFirebase.getUser(user.uid);

currentUser = new User(currentUser.uid, currentUser.displayName, fbUser.isModerator, currentUser.email, currentUser.emailVerified, currentUser.isAnonymous, currentUser.phoneNumber, currentUser.photoURL);
}
fn(currentUser);
};

return firebaseApp.auth().onAuthStateChanged(firebaseStatusChange);
};

const signOut = () => {
firebaseApp.auth().signOut();
};

const getCurrentUser = () => currentUser;

export default { onAuthStateChanged, signOut, getCurrentUser }
8 changes: 7 additions & 1 deletion src/services/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from 'react';

import authFirebase from './authFirebase'

//change the logo file to upload your own Logo
import imgHeader from '../images/logo.svg';
import LoginFirebase from "./LoginFirebase";
import dbFirebase from "./dbFirebase";

// change function request to add a real server to upload a photo
// instead of a mockup with timeout
Expand Down Expand Up @@ -44,5 +48,7 @@ const headerstyles = {
export default {
Header,
request,
loginComponentName: "LoginFirebase"
loginComponent: LoginFirebase,
authModule: authFirebase,
dbModule: dbFirebase
}
28 changes: 10 additions & 18 deletions src/services/Db.js → src/services/dbFirebase.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import {firebaseApp} from './firebaseInit.js';
import firebaseApp from './firebaseInit.js';

const db = firebaseApp.firestore();

async function fetchPhotos() {
const geojson = {
"type": "FeatureCollection",
"features": []
};

const querySnapshot = await firebaseApp.firestore().collection("photos").get();
const querySnapshot = await db.collection("photos").get();

querySnapshot.forEach( doc => {
console.log(`${doc.id} =>`, doc.data());
Expand All @@ -33,20 +35,10 @@ async function fetchPhotos() {
return geojson;
}

/**
* When the user login call fn
* @param fn
*/
const onAuthStateChanged = (fn) => {
return firebaseApp.auth().onAuthStateChanged(fn);
};

const signOut = () => {
firebaseApp.auth().signOut();
};

const currentUser = () => {
return firebaseApp.auth().currentUser;
};
async function getUser(id) {
const fbUser = await db.collection("users").doc(id).get();
debugger
return fbUser.exists ? fbUser.data() : null;
}

export default {fetchPhotos, onAuthStateChanged, signOut, currentUser};
export default {fetchPhotos, getUser};
6 changes: 1 addition & 5 deletions src/services/firebaseInit.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,4 @@ const firestore = firebaseApp.firestore();
const settings = { timestampsInSnapshots: true };
firestore.settings(settings);

const auth= firebaseApp.auth;
export {
firebaseApp,
auth
}
export default firebaseApp;
14 changes: 14 additions & 0 deletions src/types/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
class User {
constructor(id, displayName, isModerator, email, emailVerified, isAnonymous, phoneNumber, photoURL) {
this.id = id;
this.displayName = displayName;
this.isModerator = isModerator;
this.email = email;
this.emailVerified = emailVerified;
this.isAnonymous = isAnonymous;
this.phoneNumber = phoneNumber;
this.photoURL = photoURL;
}
}

export default User;

0 comments on commit 18cdc12

Please sign in to comment.