commit
94ab7162e9
@ -0,0 +1,21 @@ |
||||
# See https://help.github.com/ignore-files/ for more about ignoring files. |
||||
|
||||
# dependencies |
||||
/node_modules |
||||
|
||||
# testing |
||||
/coverage |
||||
|
||||
# production |
||||
/build |
||||
|
||||
# misc |
||||
.DS_Store |
||||
.env.local |
||||
.env.development.local |
||||
.env.test.local |
||||
.env.production.local |
||||
|
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
@ -0,0 +1,161 @@ |
||||
User Admin: |
||||
|
||||
Only users that are server admins can use these APIs. A user can be marked as a server admin by updating the database directly, e.g.: |
||||
|
||||
UPDATE users SET admin = 1 WHERE name = '@foo:bar.com' |
||||
|
||||
Create user: |
||||
|
||||
Remove/deactivate user: |
||||
|
||||
should we be able to hard remove (GDPR) |
||||
|
||||
Deactivate Account: |
||||
|
||||
This API deactivates an account. It removes active access tokens, resets the password, and deletes third-party IDs (to prevent the user requesting a password reset). |
||||
The api is: |
||||
POST /_matrix/client/r0/admin/deactivate/<user_id> |
||||
|
||||
including an access_token of a server admin, and an empty request body. |
||||
|
||||
Destroy room: |
||||
remove all users and block access or remove all trace of room in db? |
||||
|
||||
Deactivate room: |
||||
can it be reactivated? |
||||
|
||||
|
||||
|
||||
Reset password: |
||||
|
||||
Changes the password of another user. |
||||
|
||||
The api is: |
||||
|
||||
POST /_matrix/client/r0/admin/reset_password/<user_id> |
||||
|
||||
with a body of: |
||||
|
||||
{ |
||||
"new_password": "<secret>" |
||||
} |
||||
|
||||
including an access_token of a server admin. |
||||
|
||||
|
||||
Display rooms list: |
||||
|
||||
Show users list: |
||||
|
||||
statistics: facturation, number of messages, check by users access to active session, device, location |
||||
|
||||
|
||||
Hello, |
||||
pour l'interface de paramétrage / suivi pour nos intégrateurs, j'ai identifié les phases de vie / actions / infos. Pourriez-vous svp me dire si c'est complet ? dès que nous sommes alignés je fais une proposition d'IHM si ça vous va: |
||||
1/ Installation : |
||||
Nom de l’entreprise |
||||
Noms prénoms mails des participants |
||||
|
||||
2/ Maintien : |
||||
Etat du serveur ok / ok |
||||
Nombre de rooms |
||||
Mémoire utilisée |
||||
Listes des users et invités |
||||
Accès aux logs ? lesquels ? |
||||
|
||||
Ajouter des participants |
||||
Nom prénom mail |
||||
Supprimer des participants |
||||
Pick from list |
||||
|
||||
Next step : archivage des rooms |
||||
|
||||
1/ Installation : |
||||
Nom de l’entreprise |
||||
Noms prénoms mails des participants |
||||
|
||||
2/ Maintien : |
||||
Etat du serveur ok / ok |
||||
Nombre de rooms |
||||
Mémoire utilisée |
||||
Listes des users et invités |
||||
Accès aux logs ? lesquels ? |
||||
|
||||
Ajouter des participants |
||||
Nom prénom mail |
||||
Supprimer des participants |
||||
Pick from list |
||||
|
||||
Next step : archivage des rooms |
||||
|
||||
1/ Installation : |
||||
Nom de l’entreprise |
||||
Noms prénoms mails des participants |
||||
|
||||
2/ Maintien : |
||||
Etat du serveur ok / ok |
||||
Nombre de rooms |
||||
Mémoire utilisée |
||||
Listes des users et invités |
||||
Accès aux logs ? lesquels ? |
||||
|
||||
Ajouter des participants |
||||
Nom prénom mail |
||||
Supprimer des participants |
||||
Pick from list |
||||
|
||||
Next step : archivage des rooms |
||||
Alexandre Storelli |
||||
Je verrais aussi nom du sous-domaine voulu |
||||
Du genre Bernard et Dugenou Avocats pourraient vouloir avoir bdavocats.watcha.fr |
||||
Autre item pour installation: serveur mail interne ou sendinblue |
||||
Maintien: changer l'admin |
||||
Distinction entre supprimer participant (bloquer son compte) et supprimer participant (supprimer compte et messages) |
||||
Xavier |
||||
thx Alex, je pensais que l'on figeait automatiquement le nom de domaine en faisant nomentreprise.domaineintégrateur.xx (ce peut être le nom de domaine de l'intégrateur) |
||||
merci pour les autres remarques |
||||
Alexandre Storelli |
||||
un nom d'entreprise n'est pas unique, il y a un risque de collisions. Par exemple watcha https://www.societe.com/cgi-bin/search?champs=watcha |
||||
sinon OK bien sûr pour le sous-domaine chez l'intégrateur |
||||
Xavier |
||||
Tu as raison! |
||||
|
||||
pour nos intégrateurs: quel sera selon vous le serveur mail? ils utilisent le notre? on leur en déploie un? |
||||
dez je crois qu'on en avait déjà parlé |
||||
Alexandre Storelli |
||||
Et t'as des noms d'entreprises très longs, du genre https://www.societe.com/societe/picardie-maritime-habitat-fondation-paul-duclercq-005720610.html du coup il faut pouvoir choisir la façon de l'abréger |
||||
Pour les serveurs mail, on peut proposer le nôtre par défaut, et donner une option à l'intégrateur pour mettre celui qu'il souhaite (champs SMTP, port, login, mdp, protocole...) |
||||
Ce n'est pas à nous d'en déployer un à mon sens, mais c'est un truc qu'ils maîtrisent bien |
||||
Xavier |
||||
c'est pas des emmerdes en plus pour nous? (certificats, etc...) pas plus simple d'imposer le notre? |
||||
Alexandre Storelli |
||||
Ça ne me semble pas poser de souci particulier. Au contraire, vu que c'est délicat d'envoyer un mail qui n'arrive pas dans les spams depuis un canon à mail, les serveurs déjà existants des boîtes clientes feront un meilleur travail |
||||
De plus, c'est un gros argument de confidentialité pour les clients |
||||
Car on ne peut pas être sûr qu'il n'y a pas de petits malins chez SendInBlue qui lisent nos emails |
||||
Alors que sur le serveur mail de Résophone, il y a des types de résophone qui veillent au grain et ça devient leur problème, plus le nôtre |
||||
François G |
||||
+1 |
||||
Xavier |
||||
c'est beau cet alignement des astres ;-) |
||||
merci à vous |
||||
Alexandre Storelli |
||||
J'ajouterais aussi un état des lieux sur la facturation, en lien avec une liste donnée de salons (si ça a lieu d'être) |
||||
Xavier |
||||
oui tu as raison: je mentionne Nombre de rooms et Mémoire utilisée mais il faut aussi le forfait en cours |
||||
Alexandre Storelli |
||||
Ah oui pardon je n'avais pas lu assez attentivement |
||||
Xavier |
||||
non non c'est très bien ça me fait penser à ajouter le forfait en cours |
||||
Alexandre Storelli |
||||
ok :) |
||||
Pour les logs, c'est dur à dire. Fournir l'intégralité des logs de nos différentes briques est un peu violent. Mais donner cet accès peut aussi être un gage de transparence et leur sous-entendre que c'est aussi à eux de les serveiller. |
||||
*surveiller |
||||
Sylvain |
||||
Cool le fix de setup account alex ca marche nickel |
||||
Alexandre Storelli |
||||
Super! |
||||
J'ai pas mal avancé sur la page du site pour les apps mobiles |
||||
Sylvain |
||||
good |
||||
Alexandre Storelli |
||||
Pour les logs, après réflexion, je suis favorable à donner l'intégralité des accès à l'intégrateur. Présenté sous forme d'onglets selon chaque thématique (serveur, conf, système...). Ça facilitera la communication entre l'intégrateur et nous s'il faut faire du debug ou analyser des attaques. François G & Sylvain quelle est votre position sur la question? |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,20 @@ |
||||
{ |
||||
"name": "console_admin", |
||||
"version": "0.1.0", |
||||
"private": true, |
||||
"dependencies": { |
||||
"react": "^16.4.2", |
||||
"react-dom": "^16.4.2", |
||||
"react-scripts": "1.1.5" |
||||
}, |
||||
"scripts": { |
||||
"start": "react-scripts start", |
||||
"build": "react-scripts build", |
||||
"test": "react-scripts test --env=jsdom", |
||||
"eject": "react-scripts eject" |
||||
}, |
||||
"devDependencies": { |
||||
"bootstrap": "^4.1.3", |
||||
"react-bootstrap": "^0.32.3" |
||||
} |
||||
} |
After Width: | Height: | Size: 3.8 KiB |
@ -0,0 +1,45 @@ |
||||
<!DOCTYPE html> |
||||
<!-- Latest compiled and minified CSS --> |
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> |
||||
|
||||
<!-- Optional theme --> |
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
||||
<meta name="theme-color" content="#000000"> |
||||
<!-- |
||||
manifest.json provides metadata used when your web app is added to the |
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/ |
||||
--> |
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"> |
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> |
||||
<!-- |
||||
Notice the use of %PUBLIC_URL% in the tags above. |
||||
It will be replaced with the URL of the `public` folder during the build. |
||||
Only files inside the `public` folder can be referenced from the HTML. |
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will |
||||
work correctly both with client-side routing and a non-root public URL. |
||||
Learn how to configure a non-root public URL by running `npm run build`. |
||||
--> |
||||
<title>React App</title> |
||||
</head> |
||||
<body> |
||||
<noscript> |
||||
You need to enable JavaScript to run this app. |
||||
</noscript> |
||||
<div id="root"></div> |
||||
<!-- |
||||
This HTML file is a template. |
||||
If you open it directly in the browser, you will see an empty page. |
||||
|
||||
You can add webfonts, meta tags, or analytics to this file. |
||||
The build step will place the bundled scripts into the <body> tag. |
||||
|
||||
To begin the development, run `npm start` or `yarn start`. |
||||
To create a production bundle, use `npm run build` or `yarn build`. |
||||
--> |
||||
</body> |
||||
</html> |
@ -0,0 +1,15 @@ |
||||
{ |
||||
"short_name": "React App", |
||||
"name": "Create React App Sample", |
||||
"icons": [ |
||||
{ |
||||
"src": "favicon.ico", |
||||
"sizes": "64x64 32x32 24x24 16x16", |
||||
"type": "image/x-icon" |
||||
} |
||||
], |
||||
"start_url": "./index.html", |
||||
"display": "standalone", |
||||
"theme_color": "#000000", |
||||
"background_color": "#ffffff" |
||||
} |
@ -0,0 +1,28 @@ |
||||
|
||||
.App { |
||||
text-align: center; |
||||
} |
||||
|
||||
.App-logo { |
||||
animation: App-logo-spin infinite 20s linear; |
||||
height: 80px; |
||||
} |
||||
|
||||
.App-header { |
||||
background-color: #222; |
||||
height: 150px; |
||||
padding: 20px; |
||||
color: white; |
||||
} |
||||
|
||||
.App-title { |
||||
font-size: 1.5em; |
||||
} |
||||
.App-intro { |
||||
font-size: large; |
||||
} |
||||
|
||||
@keyframes App-logo-spin { |
||||
from { transform: rotate(0deg); } |
||||
to { transform: rotate(360deg); } |
||||
} |
@ -0,0 +1,53 @@ |
||||
import React, { Component } from 'react'; |
||||
import logo from './logo.svg'; |
||||
import './App.css'; |
||||
import {Bootstrap, Grid, Row, Col, Button,FormGroup,ControlLabel,FormControl,HelpBlock} from 'react-bootstrap'; |
||||
|
||||
|
||||
|
||||
class App extends Component { |
||||
constructor(props, context) { |
||||
super(props, context); |
||||
|
||||
this.handleChange = this.handleChange.bind(this); |
||||
|
||||
this.state = { |
||||
value: '' |
||||
}; |
||||
} |
||||
|
||||
getValidationState() { |
||||
const length = this.state.value.length; |
||||
if (length > 10) return 'success'; |
||||
else if (length > 5) return 'warning'; |
||||
else if (length > 0) return 'error'; |
||||
return null; |
||||
} |
||||
|
||||
handleChange(e) { |
||||
this.setState({ value: e.target.value }); |
||||
} |
||||
render() { |
||||
return ( |
||||
<form> |
||||
<FormGroup |
||||
controlId="formBasicText" |
||||
validationState={this.getValidationState()} |
||||
> |
||||
<ControlLabel>Working example with validation</ControlLabel> |
||||
<FormControl |
||||
type="text" |
||||
value={this.state.value} |
||||
placeholder="Enter text" |
||||
onChange={this.handleChange} |
||||
/> |
||||
<FormControl.Feedback /> |
||||
<HelpBlock>Validation is based on string length.</HelpBlock> |
||||
</FormGroup> |
||||
</form> |
||||
|
||||
); |
||||
} |
||||
} |
||||
|
||||
export default App; |
@ -0,0 +1,9 @@ |
||||
import React from 'react'; |
||||
import ReactDOM from 'react-dom'; |
||||
import App from './App'; |
||||
|
||||
it('renders without crashing', () => { |
||||
const div = document.createElement('div'); |
||||
ReactDOM.render(<App />, div); |
||||
ReactDOM.unmountComponentAtNode(div); |
||||
}); |
@ -0,0 +1,5 @@ |
||||
body { |
||||
margin: 0; |
||||
padding: 0; |
||||
font-family: sans-serif; |
||||
} |
@ -0,0 +1,8 @@ |
||||
import React from 'react'; |
||||
import ReactDOM from 'react-dom'; |
||||
import './index.css'; |
||||
import App from './App'; |
||||
import registerServiceWorker from './registerServiceWorker'; |
||||
|
||||
ReactDOM.render(<App />, document.getElementById('root')); |
||||
registerServiceWorker(); |
After Width: | Height: | Size: 2.6 KiB |
@ -0,0 +1,117 @@ |
||||
// In production, we register a service worker to serve assets from local cache.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on the "N+1" visit to a page, since previously
|
||||
// cached resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
|
||||
// This link also includes instructions on opting out of this behavior.
|
||||
|
||||
const isLocalhost = Boolean( |
||||
window.location.hostname === 'localhost' || |
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' || |
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match( |
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ |
||||
) |
||||
); |
||||
|
||||
export default function register() { |
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { |
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location); |
||||
if (publicUrl.origin !== window.location.origin) { |
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
|
||||
return; |
||||
} |
||||
|
||||
window.addEventListener('load', () => { |
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; |
||||
|
||||
if (isLocalhost) { |
||||
// This is running on localhost. Lets check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl); |
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => { |
||||
console.log( |
||||
'This web app is being served cache-first by a service ' + |
||||
'worker. To learn more, visit https://goo.gl/SC7cgQ' |
||||
); |
||||
}); |
||||
} else { |
||||
// Is not local host. Just register service worker
|
||||
registerValidSW(swUrl); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
function registerValidSW(swUrl) { |
||||
navigator.serviceWorker |
||||
.register(swUrl) |
||||
.then(registration => { |
||||
registration.onupdatefound = () => { |
||||
const installingWorker = registration.installing; |
||||
installingWorker.onstatechange = () => { |
||||
if (installingWorker.state === 'installed') { |
||||
if (navigator.serviceWorker.controller) { |
||||
// At this point, the old content will have been purged and
|
||||
// the fresh content will have been added to the cache.
|
||||
// It's the perfect time to display a "New content is
|
||||
// available; please refresh." message in your web app.
|
||||
console.log('New content is available; please refresh.'); |
||||
} else { |
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.'); |
||||
} |
||||
} |
||||
}; |
||||
}; |
||||
}) |
||||
.catch(error => { |
||||
console.error('Error during service worker registration:', error); |
||||
}); |
||||
} |
||||
|
||||
function checkValidServiceWorker(swUrl) { |
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl) |
||||
.then(response => { |
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
if ( |
||||
response.status === 404 || |
||||
response.headers.get('content-type').indexOf('javascript') === -1 |
||||
) { |
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => { |
||||
registration.unregister().then(() => { |
||||
window.location.reload(); |
||||
}); |
||||
}); |
||||
} else { |
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl); |
||||
} |
||||
}) |
||||
.catch(() => { |
||||
console.log( |
||||
'No internet connection found. App is running in offline mode.' |
||||
); |
||||
}); |
||||
} |
||||
|
||||
export function unregister() { |
||||
if ('serviceWorker' in navigator) { |
||||
navigator.serviceWorker.ready.then(registration => { |
||||
registration.unregister(); |
||||
}); |
||||
} |
||||
} |
Loading…
Reference in new issue