Changelog
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
Generated by ``auto-changelog` <https://github.com/CookPete/auto-changelog>`_.
1.3.0
19 May 2026 — Header logo / title anchor click target is now configurable. Public API gains one keyword argument (
logo_link_url) on bothFlaskS3Viewer.__init__andadd_new_one; existing callers that omit the kwarg see no behaviour change — the v1.2 HTMX swap remains the default.
Added
logo_link_urlconstructor argument (and matchingadd_new_onekwarg). When set, the header logo + title anchor renders as a plain<a href="...">pointing at the configured URL instead of the default HTMX listing reset, so the brand mark can return users to an external dashboard / home page. The HTMX swap attributes (hx-get/hx-target/hx-push-url) are dropped in this mode to ensure a standard full-page navigation; other listing HTMX flows (file rows, pagination, search, bucket switcher) are unaffected. Multi-namespace semantics follow the established_INHERITsentinel pattern: omit onadd_new_oneto inherit the parent viewer’s value, passNoneexplicitly to drop the override on a child namespace, or pass a different string to override per namespace. The blueprint context processor exposes the resolved value asFS3V_LOGO_LINK_URLfor templates.
Documented
New
logo_link_urlnote in the Branding (title + logo) section ofdocs/source/usage/configuration.rstcovering the HTMX swap trade-off, multi-namespace inheritance semantics, and backwards compatibility with v1.2 deployments.
1.2.0
19 May 2026 — STS AssumeRole automatic temporary credential refresh. Public API (
FlaskS3Viewerconstructor,add_new_one,init_app,get_instance,get_boto_client,get_boto_session,AWSSession.__init__) is unchanged — long-running viewers that userole_arnsimply stop hittingExpiredTokenafterDurationSecondselapses.
Added
AWSSessionnow wires the working boto3 session against botocore’sRefreshableCredentialswheneverrole_arnis set and either MFA is not used or atoken_code_callbackis supplied. boto3 re-invokessts:AssumeRoleautomatically when the cached credentials approach expiry (botocore defaults: 15-minute advisory window for background refresh, 10-minute mandatory window for synchronous refresh). With atoken_code_callbackthe callback fires on every refresh so each AssumeRole call carries a fresh OTP. The legacy single-shot path is preserved for themfa_serial+ literaltoken_codecombination (the consumed OTP cannot be replayed for refresh) so existing short-lived MFA workflows behave identically to v1.1.x.
Changed
AWSSession._assume_roleinternally branches into_assume_role_refreshable(default forrole_arnusers) and_assume_role_static(legacy single-shot path). External signature, kwargs, and return type are unchanged; the working session’s credentials object may now be aRefreshableCredentialsinstance (a subclass ofbotocore.credentials.Credentials) on the refresh-eligible path, soisinstance(creds, Credentials)host checks continue to pass.
Documented
New Automatic credential refresh subsection under STS AssumeRole / MFA in
docs/source/usage/configuration.rstcovering refresh eligibility, the 15-minute advisory / 10-minute mandatory refresh windows, andtoken_code_callbackinvocation semantics.New Presigned URL TTL with temporary credentials subsection documenting that presigned URL lifetime is capped to
min(Expires, STS session expiry)and recommending either long-lived IAM credentials or aduration_seconds≥ the requested presign expiry.Choosing duration_seconds guidance (≥ 3600 recommended; STS AssumeRole rate limits and the 15/10-minute advisory/mandatory refresh windows).
Using with EKS IRSA explainer for the two-stage credential chain (IRSA
AssumeRoleWithWebIdentity→ flask-s3-viewerAssumeRole).STS endpoint selection note recommending regional STS endpoints in non-
us-east-1regions (e.g. ap-northeast-2) for latency and availability.Mapping the web user to a CloudTrail identity note covering the separation between the audit
userfield and theRoleSessionNamerecorded by CloudTrail, with a PII-avoidance warning forRoleSessionNamechoices.
1.1.1
19 May 2026 — Packaging follow-up to 1.1.0.
Fixed
Pin
requests>=2.31inside the[auth]extra. Authlib’s Flask client routes Google OAuth token exchange throughauthlib.integrations.requests_client, but Authlib itself only declarescryptographyandjoserfcas install requirements, sopip install "flask-s3-viewer[auth]"had been leaving therequestsimport unresolved at runtime.
Changed
Normalize the PyPI distribution name to the canonical hyphenated form (
flask-s3-viewer) in line with PEP 503. The Python module remainsflask_s3_viewerandpip install flask_s3_viewerkeeps working — PyPI normalizes both spellings to the same project.
1.1.0
18 May 2026 — Audit logging & logging surface clean-up. The public API (
FlaskS3Viewerconstructor,add_new_one,init_app,get_instance,get_boto_client,get_boto_session) is unchanged — the changes below affect log output only.
Added
New audit logger
flask_s3_viewer.audit. Every S3 CRUD action that flows through the blueprint (list/download/upload/delete/presign) emits exactly one structured record carryingaction,namespace,key,user,result,status_code,client_ip,user_agent, and (on failure)error. Level mapping:ok→ INFO,denied→ WARNING,error→ ERROR. Activation is pure-logging: attach a handler toflask_s3_viewer.audit, set its level, optionally pinpropagate = False. No constructor flag.flask_s3_viewer.audit.emit(...)is a public helper host code may call to record extra non-CRUD operations on the same logger. Log injection is defended at this layer — ASCII control bytes in any user-controllable field (key / email / User-Agent / exception text) are escaped to\xNNbefore the record is built. UA is capped at 256 bytes; free-form fields at 1024 bytes. See Audit logging indocs/source/usage/configuration.rstfor ProxyFix guidance, JSON handler setup, and PII / ARN / bucket-name redaction filter examples.Each audit record now carries a
request_id(8 hex chars) that groups all rows from a single Flask request. Multi-file uploads / presigns and the auth/error/success rows of one request share one id, so per-file rows are joinable in JSON pipelines viarecord.request_idand grep-able in plaintext logs via thereq=<id>token appended to the human-readable message body. Outside a request context everyemit()gets a fresh id. Theemit()public signature is unchanged.Audit records now include a
bucketfield (record extra +bucket=<name>message token) reflecting the viewer’s S3 bucket name. The blueprint’surl_value_preprocessorresolves the bucket once per request so every audit row carries it without any per-view bookkeeping; emits from outside a request context yield an empty bucket unless the caller pre-setsg.FSV_AUDIT_BUCKET. Theemit()public signature is unchanged.
Changed
Internal
logging.info(...)/logging.error(...)/logging.debug(...)calls inflask_s3_viewer/__init__.py,aws/s3.py,aws/session.py, andaws/cache.pyhave been routed through per-modulelogging.getLogger(__name__)instances. Recordnamenow readsflask_s3_viewer.<module>instead ofroot. Host pipelines that filter by recordname(rather than by handler attachment) need to update their allow-lists; host pipelines that attach handlers to the root logger (or toflask_s3_viewer) are unaffected — the module loggers default topropagate=True.app.url_mapregistration dump was demoted from INFO to DEBUG so registering many namespaces (or large blueprints) no longer floods INFO logs at app startup.Audit logger now emits one row per uploaded / presigned file instead of one aggregate row per request. Each row’s
keyis the canonical per-object S3 target (<prefix><safe_name>); duplicate-basename and overwrite-conflict rejections emit oneerrorrow per violating file. The “no files iterated” cases (mkdir-only upload, emptyfile_listpresign, invalid prefix, denied auth) still emit a single prefix-keyed row. Theemit()public signature is unchanged; only the per-request emit count grew (1 → N).upload_type='presign'mode no longer pre-issues conflict-check presign URLs at file-selection time. The previous flow walked every selected file through a serialpost_presignround-trip before any chip rendered, so picking N files incurred N sequential S3 / signer hops before the user could even see what they had staged. Chips and the Upload button now appear immediately after the file picker resolves; presign URL issuance is deferred to the Upload click. Conflict (HTTP 409) and permission-denied (HTTP 403) dialogs therefore surface after Upload instead of after file selection.defaultupload mode is unaffected.core.jspublic surface (readyFileHandling,uploadFiles,preventDefaults) is unchanged — only_upload_form.htmlwas touched.add_new_one()now accepts explicit auth-related kwargs (auth_callback,permission_callback,visible_namespaces_callback,google_client_id,google_client_secret,allowed_emails,allowed_domains). Omitted kwargs inherit the parent viewer’s value; explicit values (includingNoneto mean disabled) override. Previously theor self.xfallback madeauth_callback=Noneindistinguishable from “not passed”, so a child namespace could not opt out of a parent’s auth configuration. Backward-compatible: existing callers that omit the kwarg see no behavior change.AWSS3Client.bucket_nameis now a read-only public property. The legacy private_bucket_nameattribute is retained for any host code reading it directly; new integrations should prefer the property. The blueprint’spull_divisionnow uses the public property when populatingg.FSV_AUDIT_BUCKET.Presign upload UI now disables the
<input type="file">while a presign request is in flight (fsvPresignSetUploadBusy). Previously only the Upload button was disabled, leaving a race where a second file-picker selection could overwrite the pending slot set between the click and the response from/files/presign. The label (<label for="fs3viewer_files">) is suppressed automatically by the browser when the input itself is disabled.Audit logging redaction guide now documents that the
bucketrecord extra is also a candidate for masking, with a one-line addition to theKeyErrorRedactFilterexample.
Fixed
aws/s3.py‘sPURGE:/MKDIR:/UP_OBJECT:DEBUG lines used the brokenlogging.debug('PURGE:', name)form (the second positional argument was treated as a logging-args tuple, against an unparameterised message string, which the stdlib silently drops). They now uselogger.debug('PURGE: %s', name)etc., so a host that pins the logger at DEBUG actually sees the keys involved in each cache invalidation / placeholder create / upload event.
1.0.1
15 May 2026
Fixed
Polished upload selection spacing and rebuilt the generated Tailwind CSS.
Added a dismiss control to permission error toasts and shortened their auto-dismiss timing.
1.0.0
15 May 2026 — first stable 1.0 release.
Added
Authentication & permission framework. Two opt-in layers, both off by default to preserve the legacy anonymous experience: (a) hook framework —
auth_callback(request) -> email | Noneandpermission_callback(email, action, namespace, key) -> bool, whereactionis one ofACTION_LIST/ACTION_DOWNLOAD/ACTION_UPLOAD/ACTION_DELETE/ACTION_PRESIGN; (b) built-in Google OAuth via Authlib (optional[auth]extra), wired by passinggoogle_client_id/google_client_secret. Convenience builderemail_allowlist(emails=..., domains=...)and constructor kwargsallowed_emails/allowed_domainsshort-circuit the common allow-list case. Routes/auth/login,/auth/callback,/auth/logoutare installed as app-level routes outside the namespace prefix — one OAuth redirect URI per Flask app even when multiple FlaskS3Viewer namespaces are mounted, and namespace renames don’t require Google Console updates. Anonymous browser GETs are redirected through Google sign-in when configured; non-browser callers still get bare 401/403.Logged-in user widget in the file listing header: when auth is wired and the request has an identity, the user’s email + a logout button render next to the theme toggle. Identity is resolved via
viewer.auth_callback(request)so custom integrations show the right user, not just Google sessions.Parent-folder (
..) row at the top of every sub-prefix listing. Familiar file-browser UX; uses the same HTMX partial swap as folder rows so there is no full page reload. Omitted at root.
Changed
Listing search rewritten from JMESPath f-string interpolation to a Python case-insensitive
infilter with NFC normalisation. Concrete wins:Unicode-safe — Korean, Japanese, accented Latin, and emoji queries all match (was ASCII-only).
Case-insensitive —
README.MDmatchesreadme.Current-folder scoped — search stays on the current listing level, filtering only direct child files and folders under the active prefix.
NFC normalisation on both query and key — macOS Finder uploads land in S3 as NFD-decomposed Hangul (
ㅅ+ㅡ+...) but the browser IME emits NFC (스+...); without this, partial queries silently found nothing.``base_path`` is excluded from the comparison so the mount point doesn’t leak into every match (e.g.
base_path='test/'no longer madetestmatch everything).Disk cache bypassed during search to avoid stale results across deployments.
No JMESPath injection seam — special characters (backtick, quote, backslash) in the query are inert.
Fixed
title/logo_url/logo_path/object_hostname/upload_typenow reach every render path. The full-page GET listing handler had been silently dropping the branding kwargs, which madeFlaskS3Viewer(title='...')look like a no-op on the main/filespage. Centralised in the blueprint context processor so future templates inherit the same data without per-handler bookkeeping.Search box keeps focus when Enter is pressed (Enter no longer triggers the form’s native submit — the 300 ms-debounced keyup trigger already runs the query).
1.0.0a1
13 May 2026 — major rewrite, pre-release. See MIGRATION.md.
Breaking changes
Drop Flask 2.x and boto3 1.28.x support. Requires Flask 3.0+, boto3 1.34+.
Remove
s3viewer.register(). The constructor (FlaskS3Viewer(app, ...)) now auto-registers, or useinit_app(app)for deferred binding (Flask extension pattern).FlaskS3Viewer.get_instance(namespace)→get_instance(app, namespace)(staticmethod). Same change forget_boto_clientandget_boto_session.Duplicate namespace registration now raises
ValueError(was silent reuse).Unknown namespace via URL returns HTTP 404 (was 500 from a
KeyError).Single unified template namespace.
template_namespace="base"|"mdl"is accepted with aDeprecationWarningand ignored. The bundledbase/andmdl/template directories are removed.CLI:
--template/-toption removed (the CLI now copies the singletemplates/directory).FlaskS3Viewer.SUPPORT_TEMPLATESconstant removed.Path-traversal tokens in user-supplied
prefixare rejected with HTTP 400. Tokens:..,., empty segment (//), backslash (\).base_pathwith leading/is normalized at construction (fixes a runtime cache crash).HTMX
DELETE /<ns>/files/<key>returns 200 instead of 204 (HX-Request flow); legacy non-HTMX clients still receive 204.Singletonmetaclass removed.type(FlaskS3Viewer)istype, no_instancesclass variable.
Added
Constructor branding options:
title(heading + browser tab),logo_url(any browser-resolvable URL), andlogo_path(local filesystem path, automatically inlined as adata:URI).Bulk multi-select with select-all and a single confirmed batch delete; confirm message distinguishes folder (recursive) vs file deletions.
“New Folder” button (header action area, prompts for a name and POSTs
prefixonly) and per-folder trash button.Refresh button in the header.
Drag-and-drop file picker: dropping files stages them on the input, the user clicks Upload to confirm (no auto-submit).
Per-file folder breadcrumb on every listing partial; navigations preserve the prefix on search via dynamic
oninputsynchronization.Inline SVG favicon (no more
/favicon.ico404).Upload progress bar with
htmx:xhr:progressevents; conflict (HTTP 409) triggers a confirm dialog and one-shot overwrite resubmission viafetch(full multipart re-send, not htmx trigger).{% block extra_head %}inlayout.htmlso downstream apps can inject custom<link>/<script>while keeping the rest of the layout.Presign upload mode (
upload_type="presign") ships with a dedicated template branch and lazy-loadsflask.s3viewer.core.js, preserving the legacy DOM IDs (fs3viewer_files,fs3viewer_prefix,fs3viewer_progress,file_chip,floading,upload_form,fs3viewer_refresh).Folder deletion now also removes the empty placeholder object created by
mkdir()(previously the placeholder survivedremove_all).Modern UI: single Tailwind 3.4 design system, dark mode toggle (with
prefers-color-schemeandlocalStoragepersist), inline heroicons, dynamic breadcrumb.HTMX 2.0.3 integration: search, navigation, pagination, upload, and delete now use partial responses (
HX-Requestheader) without full page reloads.htmx.min.jsis bundled withsha384SRI.Per-app extension registry:
app.extensions["flask_s3_viewer"][namespace].InvalidPrefixexception (subclass ofFlaskS3ViewerError) for path-traversal violations.realpathcontainment guard in the cache layer (defense in depth).pytest + moto test suite (74 cases, 83% coverage).
pip install -e ".[dev]"provides the dev tooling.GitHub Actions CI: Python 3.10/3.11/3.12 matrix, ruff + mypy + pytest + build. Tailwind build drift gate.
pyproject.toml(PEP 621 metadata + mypy + ruff config).setup.cfgremoved.setup.pyslimmed to a one-line shim.Type hints throughout. mypy
disallow_untyped_defs,check_untyped_defs,no_implicit_optional, etc. (0 issues).frontend/directory with Tailwind build pipeline (devDependency only — excluded from sdist viaprune frontend).MIGRATION.mdupgrade guide.
Fixed
Cache directory creation no longer crashes when
base_pathstarts with/.error.htmlnow uses the correctFS3V_CODE/FS3V_MESSAGEvariables (previously bound to{{ message }}/{{ code }}and silently empty).__init__.pydefaultsprofile_nameso the bucket config namedtuple cannot raise on missing key.files_deletenow mapsInvalidPrefixto HTTP 400 instead of 500 (consistent with the other three entry points).
Deferred to v1.1
mypy
strict = trueupgrade.
Authentication — STS AssumeRole + MFA
AWSSessionnow supports explicitrole_arnbased STSAssumeRoleon top of the base credentials. Combined options:role_arn,role_session_name(default"flask-s3-viewer"),external_id(cross-account),duration_seconds,mfa_serial,token_code(ortoken_code_callbackfor interactive prompts). All options live inside theconfigdict so the constructor surface is unchanged.Without
role_arnthe legacy direct-credential path is preserved — no STS call is made. boto3’s default credential chain (env vars, named profile, IMDS, ECS task role, IRSA, SSO cache, profile-basedrole_arnin~/.aws/config) keeps working as before.
Customization — template overrides
New constructor argument
template_folderlets the deployer point the viewer at a directory of Jinja overrides. The extension prepends aFileSystemLoader(template_folder)to the app’s Jinja loader using Flask’sChoiceLoaderpattern, so any user-edited template wins while not-overridden ones still resolve against the bundle. Other blueprints’ template resolution is untouched.CLI:
flask_s3_viewer -p ./outalready copied the bundledtemplates/directory; the new--with-staticflag additionally copiesstatic/(css/app.css,vendor/htmx.min.js,js/flask.s3viewer.core.js) so designers can fork the whole UI bundle in one step.
HTTP — Range requests
GET /<ns>/files/<key>now honors theRangeheader (RFC 7233). Well-formed ranges return206 Partial ContentwithContent-RangeandContent-Lengthpopulated from the boto3 response; every download response advertisesAccept-Ranges: bytesso resume-aware clients (video/audio players,curl -C -, mobile downloaders) can use it. Malformed / unsatisfiable ranges map to416 Range Not Satisfiablevia a newInvalidRangeError. Backwards-compatible: legacy full-object downloads (no Range header) still return200 OK.
Tests
tests/test_error_paths.py(7 cases) — boto3ClientErrorrecovery contract:find_one/is_exists/mkdirdegrade gracefully;add_one/remove_one/post_presignre-raise. Plus anAWSSessionconstruction-failure path where a non-ClientError Exception leavesrunnable=False.tests/test_download.py(6 cases) — Content-Disposition encoding branches: ASCII filename, RFC 5987 UTF-8 fallback for non-latin1 filenames (e.g. 한글.txt), MIME passthrough from boto3, no-cache headers, and 1 MiB streaming round-trip throughResponse(direct_passthrough=True).Total: 99 tests, 84% line coverage (
aws/s3.py68 → 73 %,aws/session.py73 → 86 %,view.py83 % stable).tests/test_extras.py(31 cases) — coverage-gap fillers: constructor guards (unknown upload_type, missing cache_dir, template_namespace deprecation warning, object_hostname trailing slash); deferredinit_app(app)flow;add_new_onemulti-bucket;get_boto_client/get_boto_sessionstaticmethods;_resolve_logobranches;errors.pyraisers; S3 wrapper utilities (find_all,removepolymorphism, root-delete guard,download_one); view branches (unknown ns 404, mkdir create + 409 conflict, upload success + 409 conflict + overwrite flow, idempotent delete, delete traversal 400). Final: 130 tests, 91% line coverage.
Lint
Enable ruff
UPrule (PEP 585 / 604). Typing imports modernized across the codebase:Optional[X]→X | None,List[X]→list[X],Set[X]→set[X],Tuple[A, B]→tuple[A, B],Union[A, B]→A | B. Runtime behavior unchanged (Python 3.10 floor enforces PEP 585/604 support). One legacy%-formatlogging.errorcall was rewritten to use the canonicallogging.error(fmt, *args)form.
Frontend
flask.s3viewer.core.jsslimmed from 372 → 159 lines. All legacy URL-param, browser-detection, search, refresh-badge, and clipboard helpers were removed (HTMX owns those flows now); the file is now a focused presigned-POST → S3 fan-out client. Public surface preserved:readyFileHandling,uploadFiles,preventDefaults. Required DOM contract (fs3viewer_files,fs3viewer_prefix,fs3viewer_progress,file_chip,file_count,floading,upload_form,fs3viewer_refresh) is pinned bytests/test_presign.py.
Packaging
Adopted PEP 639 license expression (
license = "MIT"+license-files = ["LICENSE"]) and dropped the deprecated{file = "LICENSE"}table form. Built artifacts now declareLicense-Expression: MITin their METADATA.
0.3.1
7 November 2024
Update .travis.yml ``#15` <https://github.com/hidekuma/flask-s3-viewer/pull/15>`_
Update README.md ``#14` <https://github.com/hidekuma/flask-s3-viewer/pull/14>`_
Bump flask from 1.1.1 to 2.2.5 in /example ``#12` <https://github.com/hidekuma/flask-s3-viewer/pull/12>`_
fix: update docs ``e36ad9a` <https://github.com/hidekuma/flask-s3-viewer/commit/e36ad9a6b3cb9137ca713f142f13617a49fe0d16>`_
fix: update docs ``1909e52` <https://github.com/hidekuma/flask-s3-viewer/commit/1909e52a2b846c24a2a2bd5b9b08048f19c74515>`_
fix(#13): update a function to correctly download a file with filename ``955a257` <https://github.com/hidekuma/flask-s3-viewer/commit/955a257989fff76516aa486c3694e7c0dd4023c1>`_
0.2.6
19 July 2024
feat: init 0.2.6 ``2b835a2` <https://github.com/hidekuma/flask-s3-viewer/commit/2b835a2489d08161d5b80e068628c9e2c3af0267>`_
0.2.5
19 July 2024
fix: update docs ``e71aee8` <https://github.com/hidekuma/flask-s3-viewer/commit/e71aee8a87e4bf6aeac7b97652cdf613b6e8a067>`_
fix: update quote_url ``5d54448` <https://github.com/hidekuma/flask-s3-viewer/commit/5d544485a0c5937d4653bb81a62754f0726941b7>`_
fix: update docs ``82d57b8` <https://github.com/hidekuma/flask-s3-viewer/commit/82d57b8e49a2e9171314a8ab3b7d7135482b41c0>`_
0.2.4
22 May 2024
Adding support to supply custom cert for endpoint urls with HTTPS ``#11` <https://github.com/hidekuma/flask-s3-viewer/pull/11>`_
pass session token through to boto ``#9` <https://github.com/hidekuma/flask-s3-viewer/pull/9>`_
doc: update docs ``27acf4e` <https://github.com/hidekuma/flask-s3-viewer/commit/27acf4e6fed61d8492218eee7ab794571aa517a7>`_
doc ``648bc3e` <https://github.com/hidekuma/flask-s3-viewer/commit/648bc3e3f525979dbd2a6c8efb3ac0dfd70ec7d0>`_
doc: updated changelog ``7990375` <https://github.com/hidekuma/flask-s3-viewer/commit/79903757c11b323a977fc1a82dedf7f3f634b1ce>`_
0.2.2
7 September 2021
Bump jinja2 from 2.11.2 to 2.11.3 ``#3` <https://github.com/hidekuma/flask-s3-viewer/pull/3>`_
Bump pygments from 2.6.1 to 2.7.4 ``#4` <https://github.com/hidekuma/flask-s3-viewer/pull/4>`_
Bump bleach from 3.1.4 to 3.3.0 ``#2` <https://github.com/hidekuma/flask-s3-viewer/pull/2>`_
Updatetd dependencies ``618499e` <https://github.com/hidekuma/flask-s3-viewer/commit/618499e12ced35ee8439664bd02507730fe6eeff>`_
chore: update dependencies ``4ccfbe1` <https://github.com/hidekuma/flask-s3-viewer/commit/4ccfbe15a11093b9e46e4819471e8dd55264a6fc>`_
fix(upload): update multipart uploading’s threshold ``f1c6799` <https://github.com/hidekuma/flask-s3-viewer/commit/f1c67994f7837eb4b9034fb23d64d608f33c134f>`_
0.2.1
27 November 2020
Updated changelog ``8b83d92` <https://github.com/hidekuma/flask-s3-viewer/commit/8b83d92477f72c8ab5b3a68e31fe57c655b001c3>`_
Updated youtube link ``75dc6c5` <https://github.com/hidekuma/flask-s3-viewer/commit/75dc6c538626863dbbfeb77da690341a5425b8ca>`_
Updated youtube links ``9053732` <https://github.com/hidekuma/flask-s3-viewer/commit/905373229f11a5505e7a43155de099af7884bbc9>`_
0.2.0
31 October 2020
Updated changelog ``2d25b36` <https://github.com/hidekuma/flask-s3-viewer/commit/2d25b36e388185c1a59159dbb6b63ca865b72c09>`_
Updated setup.py ``0500624` <https://github.com/hidekuma/flask-s3-viewer/commit/050062457a2955f12ab56223bd37daaf97f1bf88>`_
Updated setup.py ``09a7274` <https://github.com/hidekuma/flask-s3-viewer/commit/09a7274cd177ea53f2144645dd55a7fe6f701a8f>`_
0.1.2
31 October 2020
Updated docs ``d7697e6` <https://github.com/hidekuma/flask-s3-viewer/commit/d7697e6f0e74d5f1a55487d1e22bb124dca210d7>`_
Fixed bugs ``762121b` <https://github.com/hidekuma/flask-s3-viewer/commit/762121b688c0960239ce1a701e94ff12ed256608>`_
Added twine*.sh ``8093d6d` <https://github.com/hidekuma/flask-s3-viewer/commit/8093d6d13f354a75e65e9956a8438edcdc13300f>`_
0.1.1
30 April 2020
Updated version ``dae3117` <https://github.com/hidekuma/flask-s3-viewer/commit/dae311732653cedc2d4a793d925fb97536b55982>`_
0.1.0
30 April 2020
Change source’s name FlaskS3up to FlaskS3Viewer ``bf8e811` <https://github.com/hidekuma/flask-s3-viewer/commit/bf8e811f7468042aa095b14c735e4577f183abcd>`_
Updated changelog ``fd41198` <https://github.com/hidekuma/flask-s3-viewer/commit/fd411987a1aecc362e255bdaf8f9ccc897657442>`_
0.0.16
26 April 2020
Updated changelog ``4197794` <https://github.com/hidekuma/flask-s3-viewer/commit/4197794b40cdc780e7f3cd3c97dbcad5d853fb61>`_
Added gitattributes ``50b13bd` <https://github.com/hidekuma/flask-s3-viewer/commit/50b13bdc317a25eebe6323f06489613f6e493901>`_
Updated version ``150b971` <https://github.com/hidekuma/flask-s3-viewer/commit/150b971e163996c03e0a2efbe62f38c3386eca4a>`_
0.0.15
16 April 2020
Updated docs ``2ef0c0a` <https://github.com/hidekuma/flask-s3-viewer/commit/2ef0c0a40936f1051a1ee81633983b5fd8ba393b>`_
Updated docs ``e5973c3` <https://github.com/hidekuma/flask-s3-viewer/commit/e5973c3f1e41c2781e8a0fad94e333433a104f95>`_
Updated docs ``b92f93d` <https://github.com/hidekuma/flask-s3-viewer/commit/b92f93d44e8ed3ebf17d0e528e0028f4a7a1f180>`_
0.0.14
14 April 2020
Updated docs ``c236eb8` <https://github.com/hidekuma/flask-s3-viewer/commit/c236eb8c15913e8a96487634fe0d6705bfb0f229>`_
Updated docs ``9dc8c2f` <https://github.com/hidekuma/flask-s3-viewer/commit/9dc8c2f94ed9e16ade5d7c96ffc884efff2f26e2>`_
Fixed install bug ``b203e74` <https://github.com/hidekuma/flask-s3-viewer/commit/b203e74b790a8155337720abfba7c5a09c6bfa0d>`_
0.0.13
14 April 2020
Updated docs ``de51365` <https://github.com/hidekuma/flask-s3-viewer/commit/de513658dd960ae3fd81713297e1fb480b3efb97>`_
Updated README.md ``39753b1` <https://github.com/hidekuma/flask-s3-viewer/commit/39753b159200a585a27e88019f55fe0f1237f43b>`_
Updated requiements.txt of example.py ``a16a48e` <https://github.com/hidekuma/flask-s3-viewer/commit/a16a48eeb521d6675b47cd8ca41f5b7d335dcbe1>`_
0.0.12
10 April 2020
Resolved #1 about Large file controll ``#1` <https://github.com/hidekuma/flask-s3-viewer/issues/1>`_
Updated CHANGELOG ``3780688` <https://github.com/hidekuma/flask-s3-viewer/commit/37806886fffabae0acee5c3db2f5ad17f4208099>`_
Updated versions ``e678fd6` <https://github.com/hidekuma/flask-s3-viewer/commit/e678fd67ec8a89f10de6fe0713839985be622992>`_
0.0.11
7 April 2020
Updated README.md ``c0ed960` <https://github.com/hidekuma/flask-s3-viewer/commit/c0ed96041a2327a77201a358db1bb2b32431a59d>`_
Updated README ``cdb8f78` <https://github.com/hidekuma/flask-s3-viewer/commit/cdb8f7866e19bb0413672eff9281c35440e3c032>`_
Updated github links ``c7991d1` <https://github.com/hidekuma/flask-s3-viewer/commit/c7991d1923103dc516b359e15f63e944eb371a6a>`_
0.0.10
7 April 2020
Updated CHANGELOG ``fa2939f` <https://github.com/hidekuma/flask-s3-viewer/commit/fa2939f83d3b816da398f4a77fa163f0988fcf9e>`_
Updated setup.py ``5cdebf6` <https://github.com/hidekuma/flask-s3-viewer/commit/5cdebf670f88398bfe0f4aea8ad8a520c3d88d68>`_
Updated README.md ``98eb88c` <https://github.com/hidekuma/flask-s3-viewer/commit/98eb88cb7b0af94a3c511278ef465adb0246caca>`_
0.0.9
7 April 2020
Updated license ``baa2bae` <https://github.com/hidekuma/flask-s3-viewer/commit/baa2bae8382a22f529d26ed68a9db932afe8865b>`_
Updated changelog ``3a422cb` <https://github.com/hidekuma/flask-s3-viewer/commit/3a422cbdf1484e4eab225d0a3ededd6ac9630749>`_
Deleted LICENSE ``64b3bc1` <https://github.com/hidekuma/flask-s3-viewer/commit/64b3bc17504cc8dbcc52b13644e7dd475265aaeb>`_
0.0.8
6 April 2020
Updated changelog ``b157cd7` <https://github.com/hidekuma/flask-s3-viewer/commit/b157cd7e07b483e4def3acb393dc776e5d73ccc1>`_
Updated README.md and logo ``cd95649` <https://github.com/hidekuma/flask-s3-viewer/commit/cd95649f22aee8fa0ab36a047a1336966532e893>`_
Updated setup.py ``04ba882` <https://github.com/hidekuma/flask-s3-viewer/commit/04ba8820ae3fe6119a13ab7d10e7daed1ac59ff0>`_
0.0.7
6 April 2020
Updated cores ``ac41d10` <https://github.com/hidekuma/flask-s3-viewer/commit/ac41d109e14b397c4513c2d2ba920c8d137fd9a7>`_
Updated cors ``f29aacc` <https://github.com/hidekuma/flask-s3-viewer/commit/f29aacc5a72d14bc006c631a0c00a89023bda54b>`_
Init repo ``060dc79` <https://github.com/hidekuma/flask-s3-viewer/commit/060dc79560921fe3c84a470d7da338f65d0ff2ee>`_