API & Client - archive max size must be greater than files size - #70
This commit is contained in:
parent
ae53aaecd7
commit
c4e579dd25
@ -130,6 +130,11 @@ def update_application_config(auth_user_id: int) -> Union[Dict, HttpResponse]:
|
||||
if 'max_users' in config_data:
|
||||
config.max_users = config_data.get('max_users')
|
||||
|
||||
if config.max_zip_file_size < config.max_single_file_size:
|
||||
return InvalidPayloadErrorResponse(
|
||||
'Max. size of zip archive must be equal or greater than '
|
||||
'max. size of uploaded files'
|
||||
)
|
||||
db.session.commit()
|
||||
update_app_config_from_database(current_app, config)
|
||||
return {'status': 'success', 'data': config.serialize()}
|
||||
|
6
fittrackee/dist/asset-manifest.json
vendored
6
fittrackee/dist/asset-manifest.json
vendored
@ -1,8 +1,8 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "/static/css/main.376b8924.chunk.css",
|
||||
"main.js": "/static/js/main.8faa878d.chunk.js",
|
||||
"main.js.map": "/static/js/main.8faa878d.chunk.js.map",
|
||||
"main.js": "/static/js/main.7c5c861a.chunk.js",
|
||||
"main.js.map": "/static/js/main.7c5c861a.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.1240af94.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.1240af94.js.map",
|
||||
"static/js/2.301144a0.chunk.js": "/static/js/2.301144a0.chunk.js",
|
||||
@ -19,6 +19,6 @@
|
||||
"static/js/runtime-main.1240af94.js",
|
||||
"static/js/2.301144a0.chunk.js",
|
||||
"static/css/main.376b8924.chunk.css",
|
||||
"static/js/main.8faa878d.chunk.js"
|
||||
"static/js/main.7c5c861a.chunk.js"
|
||||
]
|
||||
}
|
2
fittrackee/dist/index.html
vendored
2
fittrackee/dist/index.html
vendored
@ -1 +1 @@
|
||||
<!doctype html><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"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/foundation-icons/3.0/foundation-icons.min.css"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""><title>FitTrackee</title><link href="/static/css/main.376b8924.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script><script type="text/javascript">$(document).ready((function(){$("li.nav-item").click((function(){$("button.navbar-toggler").toggleClass("collapsed"),$("#navbarSupportedContent").toggleClass("show")}))}))</script><script>!function(e){function t(t){for(var n,i,l=t[0],f=t[1],a=t[2],p=0,s=[];p<l.length;p++)i=l[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,l=1;l<r.length;l++){var f=r[l];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=i(i.s=r[0]))}return e}var n={},o={1:0},u=[];function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=n,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/";var l=this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[],f=l.push.bind(l);l.push=t,l=l.slice();for(var a=0;a<l.length;a++)t(l[a]);var c=f;r()}([])</script><script src="/static/js/2.301144a0.chunk.js"></script><script src="/static/js/main.8faa878d.chunk.js"></script></body></html>
|
||||
<!doctype html><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"><link rel="manifest" href="/manifest.json"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.1.7/css/fork-awesome.min.css" integrity="sha256-gsmEoJAws/Kd3CjuOQzLie5Q3yshhvmo7YNtBG7aaEY=" crossorigin="anonymous"><link rel="stylesheet" href="https://cdn.jsdelivr.net/foundation-icons/3.0/foundation-icons.min.css"><link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css" integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ==" crossorigin=""><title>FitTrackee</title><link href="/static/css/main.376b8924.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script><script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script><script type="text/javascript">$(document).ready((function(){$("li.nav-item").click((function(){$("button.navbar-toggler").toggleClass("collapsed"),$("#navbarSupportedContent").toggleClass("show")}))}))</script><script>!function(e){function t(t){for(var n,i,l=t[0],f=t[1],a=t[2],p=0,s=[];p<l.length;p++)i=l[p],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&s.push(o[i][0]),o[i]=0;for(n in f)Object.prototype.hasOwnProperty.call(f,n)&&(e[n]=f[n]);for(c&&c(t);s.length;)s.shift()();return u.push.apply(u,a||[]),r()}function r(){for(var e,t=0;t<u.length;t++){for(var r=u[t],n=!0,l=1;l<r.length;l++){var f=r[l];0!==o[f]&&(n=!1)}n&&(u.splice(t--,1),e=i(i.s=r[0]))}return e}var n={},o={1:0},u=[];function i(t){if(n[t])return n[t].exports;var r=n[t]={i:t,l:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=n,i.d=function(e,t,r){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(i.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var n in e)i.d(r,n,function(t){return e[t]}.bind(null,n));return r},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/";var l=this.webpackJsonpfittrackee_client=this.webpackJsonpfittrackee_client||[],f=l.push.bind(l);l.push=t,l=l.slice();for(var a=0;a<l.length;a++)t(l[a]);var c=f;r()}([])</script><script src="/static/js/2.301144a0.chunk.js"></script><script src="/static/js/main.7c5c861a.chunk.js"></script></body></html>
|
2
fittrackee/dist/static/js/main.7c5c861a.chunk.js
vendored
Normal file
2
fittrackee/dist/static/js/main.7c5c861a.chunk.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
fittrackee/dist/static/js/main.7c5c861a.chunk.js.map
vendored
Normal file
1
fittrackee/dist/static/js/main.7c5c861a.chunk.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -239,3 +239,40 @@ class TestUpdateConfig:
|
||||
assert response.status_code == 500
|
||||
assert 'error' in data['status']
|
||||
assert 'Error on updating configuration.' in data['message']
|
||||
|
||||
def test_it_raises_error_if_archive_max_size_is_below_files_max_size(
|
||||
self, app: Flask, user_1_admin: User
|
||||
) -> None:
|
||||
client = app.test_client()
|
||||
resp_login = client.post(
|
||||
'/api/auth/login',
|
||||
data=json.dumps(
|
||||
dict(email='admin@example.com', password='12345678')
|
||||
),
|
||||
content_type='application/json',
|
||||
)
|
||||
|
||||
response = client.patch(
|
||||
'/api/config',
|
||||
content_type='application/json',
|
||||
data=json.dumps(
|
||||
dict(
|
||||
gpx_limit_import=20,
|
||||
max_single_file_size=10000,
|
||||
max_zip_file_size=1000,
|
||||
max_users=50,
|
||||
)
|
||||
),
|
||||
headers=dict(
|
||||
Authorization='Bearer '
|
||||
+ json.loads(resp_login.data.decode())['auth_token']
|
||||
),
|
||||
)
|
||||
|
||||
data = json.loads(response.data.decode())
|
||||
assert response.status_code == 400
|
||||
assert 'error' in data['status']
|
||||
assert (
|
||||
'Max. size of zip archive must be equal or greater than max. size '
|
||||
'of uploaded files'
|
||||
) in data['message']
|
||||
|
@ -1,4 +1,5 @@
|
||||
import FitTrackeeGenericApi from '../fitTrackeeApi'
|
||||
import { history } from '../index'
|
||||
import { setError } from './index'
|
||||
|
||||
export const setAppConfig = data => ({
|
||||
@ -31,6 +32,7 @@ export const updateAppConfig = formData => dispatch =>
|
||||
.then(ret => {
|
||||
if (ret.status === 'success') {
|
||||
dispatch(setAppConfig(ret.data))
|
||||
history.push('/admin/application')
|
||||
} else {
|
||||
dispatch(setError(`application|${ret.message}`))
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import Message from '../Common/Message'
|
||||
import { updateAppConfig } from '../../actions/application'
|
||||
import { getAppData, updateAppConfig } from '../../actions/application'
|
||||
import { history } from '../../index'
|
||||
import { getFileSizeInMB } from '../../utils'
|
||||
|
||||
@ -11,7 +11,6 @@ class AdminApplication extends React.Component {
|
||||
super(props, context)
|
||||
this.state = {
|
||||
formData: {},
|
||||
isInEdition: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,15 +43,15 @@ class AdminApplication extends React.Component {
|
||||
this.setState(formData)
|
||||
}
|
||||
|
||||
toggleInEdition(e) {
|
||||
e.preventDefault()
|
||||
const { isInEdition } = this.state
|
||||
this.setState({ isInEdition: !isInEdition })
|
||||
}
|
||||
|
||||
render() {
|
||||
const { message, onHandleConfigFormSubmit, t } = this.props
|
||||
const { formData, isInEdition } = this.state
|
||||
const {
|
||||
isInEdition,
|
||||
loadAppConfig,
|
||||
message,
|
||||
onHandleConfigFormSubmit,
|
||||
t,
|
||||
} = this.props
|
||||
const { formData } = this.state
|
||||
return (
|
||||
<div>
|
||||
{message && <Message message={message} t={t} />}
|
||||
@ -71,7 +70,7 @@ class AdminApplication extends React.Component {
|
||||
isInEdition ? '' : 'form-disabled'
|
||||
}`}
|
||||
onSubmit={e => {
|
||||
this.toggleInEdition(e)
|
||||
e.preventDefault()
|
||||
onHandleConfigFormSubmit(formData)
|
||||
}}
|
||||
>
|
||||
@ -169,7 +168,11 @@ class AdminApplication extends React.Component {
|
||||
<input
|
||||
type="submit"
|
||||
className="btn btn-secondary"
|
||||
onClick={e => this.toggleInEdition(e)}
|
||||
onClick={e => {
|
||||
e.preventDefault()
|
||||
loadAppConfig()
|
||||
history.push('/admin/application')
|
||||
}}
|
||||
value={t('common:Cancel')}
|
||||
/>
|
||||
</>
|
||||
@ -179,7 +182,8 @@ class AdminApplication extends React.Component {
|
||||
type="submit"
|
||||
className="btn btn-primary"
|
||||
onClick={e => {
|
||||
this.toggleInEdition(e)
|
||||
e.preventDefault()
|
||||
history.push('/admin/application/edit')
|
||||
}}
|
||||
value={t('common:Edit')}
|
||||
/>
|
||||
@ -207,6 +211,9 @@ export default connect(
|
||||
message: state.message,
|
||||
}),
|
||||
dispatch => ({
|
||||
loadAppConfig: () => {
|
||||
dispatch(getAppData('config'))
|
||||
},
|
||||
onHandleConfigFormSubmit: formData => {
|
||||
const data = Object.assign({}, formData)
|
||||
data.max_single_file_size *= 1048576
|
||||
|
@ -28,7 +28,20 @@ function Admin(props) {
|
||||
<Route
|
||||
exact
|
||||
path="/admin/application"
|
||||
render={() => <AdminApplication appConfig={appConfig} t={t} />}
|
||||
render={() => (
|
||||
<AdminApplication
|
||||
appConfig={appConfig}
|
||||
t={t}
|
||||
isInEdition={false}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/admin/application/edit"
|
||||
render={() => (
|
||||
<AdminApplication appConfig={appConfig} t={t} isInEdition />
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
|
@ -2,7 +2,7 @@
|
||||
"3 to 12 characters required for username.": "3 to 12 characters required for username.",
|
||||
"8 characters required for password.": "8 characters required for password.",
|
||||
"An error occurred. Please contact the administrator.": "An error occurred. Please contact the administrator.",
|
||||
"workouts": "workouts",
|
||||
"application": "application",
|
||||
"Error during picture deletion.": "Error during picture deletion.",
|
||||
"Error during picture update.": "Error during picture update.",
|
||||
"Error during picture update, file size exceeds max size.": "Error during picture update, file size exceeds max size.",
|
||||
@ -14,6 +14,7 @@
|
||||
"Invalid credentials.": "Invalid credentials.",
|
||||
"Invalid payload.": "Invalid payload.",
|
||||
"Invalid token. Please log in again.": "Invalid token. Please log in again.",
|
||||
"Max. size of zip archive must be equal or greater than max. size of uploaded files": "Max. size of zip archive must be equal or greater than max. size of uploaded files",
|
||||
"No file part.": "No file part.",
|
||||
"No picture.": "No picture.",
|
||||
"No selected file.": "No selected file.",
|
||||
@ -30,6 +31,7 @@
|
||||
"statistics": "statistiques",
|
||||
"User does not exist.": "User does not exist.",
|
||||
"Valid email must be provided.\n": "Valid email must be provided.",
|
||||
"workouts": "workouts",
|
||||
"You can not delete your account, no other user has admin rights.": "You can not delete your account, no other user has admin rights.",
|
||||
"You do not have permissions.": "You do not have permissions."
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
"3 to 12 characters required for username.": "3 à 12 caractères requis pour le nom.",
|
||||
"8 characters required for password.": "8 caractères minimum pour le mot de passe.",
|
||||
"An error occurred. Please contact the administrator.": "Une erreur s'est produite. Merci de contacter l'administrateur.",
|
||||
"workouts": "séances",
|
||||
"application": "application",
|
||||
"Error during picture deletion.": "Erreur lors de la suppression de l'image.",
|
||||
"Error during picture update.": "Erreur lors de la mise à jour de l'image.",
|
||||
"Error during picture update, file size exceeds max size.": "Erreur lors de la mise à jour de l'image, la taille du ficher dépasse la taille maximum autorisée",
|
||||
@ -14,6 +14,7 @@
|
||||
"Invalid credentials.": "Identifiants invalides.",
|
||||
"Invalid payload.": "Données incorrectes.",
|
||||
"Invalid token. Please log in again.": "Jeton invalide. Merci de vous reconnecter.",
|
||||
"Max. size of zip archive must be equal or greater than max. size of uploaded files": "La taille max. d'une archive doit être supérieure ou égale à la taille max. d'un fichier",
|
||||
"No file part.": "Pas de fichier fourni.",
|
||||
"No picture.": "Pas d'image.",
|
||||
"No selected file.": "Pas de fichier sélectionné.",
|
||||
@ -30,6 +31,7 @@
|
||||
"statistics": "statistics",
|
||||
"User does not exist.": "L'utilisateur n'existe pas.",
|
||||
"Valid email must be provided.\n": "L'email fourni n'est pas valide.",
|
||||
"workouts": "séances",
|
||||
"You can not delete your account, no other user has admin rights.": "Vous ne pouvez pas supprimer votre compte, aucun autre utilisateur n'a des droits d'administration.",
|
||||
"You do not have permissions.": "Vous n'avez pas les permissions nécessaires."
|
||||
}
|
||||
|
@ -110,6 +110,7 @@ const message = (state = initial.message, action) => {
|
||||
return action.message
|
||||
case 'LOGOUT':
|
||||
case 'PROFILE_SUCCESS':
|
||||
case 'SET_APP_CONFIG':
|
||||
case 'SET_RESULTS':
|
||||
case '@@router/LOCATION_CHANGE':
|
||||
return ''
|
||||
|
Loading…
Reference in New Issue
Block a user