Archived
1
0
Fork 0

Make the application modular to have a "main" and "backend" part.

This commit is contained in:
Henrik Hautakoski 2018-10-09 22:26:01 +02:00
parent 884f721002
commit e5b0e1fcfd
No known key found for this signature in database
GPG key ID: 839F3A7EAFAEAFAA
28 changed files with 112 additions and 7 deletions

View file

@ -0,0 +1,50 @@
<div class="login-container section">
<h3>Login</h3>
<div class="alert alert-info">
<p class="text-center"><strong>Heads up!</strong> Signup is currently not available.</p>
<p>
Login using username/password can be setup after registration.
First time users can only register with third party services below
</p>
</div>
<span class="spacer"></span>
<form class="form" method="post" action="">
<div class="form-group">
{{ form.render('Email') }}
</div>
<div class="form-group">
{{ form.render('Password') }}
</div>
<div class="form-group">
{{ form.render('Login') }}
</div>
</form>
<span class="spacer"></span>
<div class="oauth">
<a class="button button-github" href="{{ url(['for': 'oauth', 'strategy': 'github']) }}">
{{ icon('brand/github') }} GitHub
</a>
<a class="button button-google" href="{{ url(['for': 'oauth', 'strategy': 'google']) }}">
{{ icon('brand/google') }} Google
</a>
<a class="button button-gitlab" href="{{ url(['for': 'oauth', 'strategy': 'gitlab']) }}">
{{ icon('brand/gitlab') }} Gitlab
</a>
<a class="button button-linkedin" href="{{ url(['for': 'oauth', 'strategy': 'linkedin']) }}">
{{ icon('brand/linkedin') }} LinkedIn
</a>
</div>
</div>

View file

@ -0,0 +1,43 @@
<div class="register">
<h2>Account registration</h2>
<div class="alert alert-info alert-dismissible" role="alert">
<strong>Information!</strong>
<p>
The form is prepared with the information provided by <strong>{{ provider }}</strong>.
Please check the information and make changes if necessary before continue.
</p>
</div>
<span class="spacer"></span>
<form class="form form-horizontal" method="post">
<div class="form-group">
{{ form.renderDecorated('email') }}
</div>
<div class="form-group">
{{ form.renderDecorated('username') }}
</div>
<div class="form-group">
{{ form.renderDecorated('first-name', ['length': 4]) }}
{{ form.renderDecorated('last-name', ['length': 4]) }}
</div>
<span class="spacer"></span>
<div class="form-group">
<div class="col-xs-12 col-xs-offset-2">
{{ form.render('submit') }}
</div>
</div>
</form>
</div>

View file

@ -0,0 +1,14 @@
<div class="section">
<h1>Callback created</h1>
<p>Set this link as callback url for the service you want to debug:</p>
<strong>{{ serverUrl() }}{{ url(['for': 'cb-endpoint', 'id': id]) }}</strong>
<a class="button button-default" href="{{ url('/callback/show/' ~ id) }}">
{{ icon('solid/eye') }} View
</a>
</div>

View file

@ -0,0 +1,69 @@
<div class="section">
<div class="clearfix">
<h2 class="pull-left">Callbacks</h2>
<div class="pull-right">
<a class="button button-large button-primary" href="{{ url('/callback/new') }}">
{{ icon('solid/plus') }} New
</a>
</div>
</div>
{% if page.items|length > 0 %}
<div class="callback-list">
{% for item in page.items %}
<div class="callback-list-item">
<div class="callback-list-item-header">
<a class="callback-list-item-name" href="/callback/show/{{ item.public_id }}">{{ item.name|e }}</a>
{% if item.countRequests() > 0 %}
<span class="badge badge-primary">
{{ item.countRequests() }} Requests
</span>
{% endif %}
</div>
<div class="callback-list-item-info">
<span>{{ icon('clock') }} Created at: {{ item.created_at }}</span>
<span>
{{ icon('paper-plane') }}
{% if item.countRequests() > 0 %}
Last request: {{ item.last_request }}
{% else %}
No requests yet.
{% endif %}
</span>
<span>
{{ icon('solid/link') }}
{{ serverUrl() }}{{ url(['for': 'cb-endpoint', 'id': item.public_id]) }}
</span>
</div>
<a class="callback-list-item-arrow" href="/callback/show/{{ item.public_id }}">
{{ icon('solid/arrow-alt-circle-right') }}
</a>
</div>
{% endfor %}
</div>
{% else %}
<div class="blankslate">
<h3>No callbacks made yet.</h3>
<p><a href="{{ url('/callback/new') }}">Create</a> a callback to begin!</p>
</div>
{% endif %}
<nav class="text-center" aria-label="Page navigation">
{{ partial('pagination') }}
</nav>
</div>

View file

@ -0,0 +1,39 @@
<div class="section center-block" style="width: 400px">
<h2>Create callback</h2>
<!--
<form class="form-horizontal" method="post">
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="name" id="name">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="submit" class="button button-brand" value="Create">
</div>
</div>
</form>
-->
<form class="form-horizontal" method="post">
<div class="form-group">
<label class="col-sm-2 control-label" for="name">Name</label>
<div class="col-sm-10">
{{ form.render('Name') }}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
{{ form.render('Create') }}
</div>
</div>
</form>
</div>

View file

@ -0,0 +1,140 @@
<div class="section">
<div class="clearfix">
<h3 class="pull-left">{{ item.name|e }}</h3>
<h5 class="pull-right"><strong>Created at:</strong> {{ item.created_at }}</h5>
</div>
<div class="panel-group request-list" id="request-list" role="tablist" aria-multiselectable="true">
{% for index, req in page.items %}
<div class="panel request-list-item">
<a id="request-item-head-{{ index }}" class="request-list-item-header collapsed"
href="#request-item-body-{{ index }}" aria-controls="request-item-body-{{ index }}"
data-parent="#request-list" data-toggle="collapse" aria-expanded="true" >
<div class="request-list-item-header-row">
<span class="request-list-item-header-method">
{{ req.getMethod() }}
</span>
<span class="request-list-item-header-uri">
<span class="url">{{ urlStyle(req.getUri()) }}</span>
</span>
<span class="request-list-item-header-timestamp">
{{ icon('clock') }} {{ req.getTimestamp() }}
</span>
</div>
<div class="request-list-item-header-row">
<span class="request-list-item-header-type">
{{ icon('file-alt') }} {{ req.getType() }}
</span>
<span class="request-list-item-header-size">
{{ icon('solid/database') }} {{ req.getSize() }} b
</span>
<span class="request-list-item-header-ip">
{{ icon('compass') }} {{ req.getSourceIp() }}
</span>
</div>
</a>
<div id="request-item-body-{{ index }}" class="collapse"
role="tabpanel" aria-labelledby="request-item-head-{{ index }}">
<div class="request-list-item-detail">
{% if req.getUriQuery()|length > 0 %}
<button class="request-list-item-detail-button" type="button"
data-toggle="collapse" data-target="#request-list-item-detail-query-{{ index }}"
aria-expanded="false" aria-controls="request-list-item-detail-query-{{ index }}">
Query
</button>
<div id="request-list-item-detail-query-{{ index }}" class="collapse in">
<table class="request-list-item-detail-headers">
<thead>
<tr>
<th class="request-list-item-detail-headers-key">Key</th>
<th class="request-list-item-detail-headers-value">Value</th>
</tr>
</thead>
<tbody>
{% for key, val in req.getUriQuery() %}
<tr>
<td><strong>{{ key|e }}</strong></td>
<td>{{ val|e }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<button class="request-list-item-detail-button" type="button"
data-toggle="collapse" data-target="#request-list-item-detail-headers-{{ index }}"
aria-expanded="false" aria-controls="request-list-item-detail-headers-{{ index }}">
Headers
</button>
<div id="request-list-item-detail-headers-{{ index }}" class="collapse">
<table class="request-list-item-detail-headers">
<thead>
<tr>
<th class="request-list-item-detail-headers-key">Key</th>
<th class="request-list-item-detail-headers-value">Value</th>
</tr>
</thead>
<tbody>
{% for key, val in req.getHeaders() %}
<tr>
<td><strong>{{ key|e }}</strong></td>
<td>{{ val|e }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<button class="request-list-item-detail-button" type="button"
data-toggle="collapse" data-target="#request-list-item-detail-body-{{ index }}"
aria-expanded="false" aria-controls="request-list-item-detail-body-{{ index }}">
Body
</button>
<div id="request-list-item-detail-body-{{ index }}" class="request-list-item-detail-body collapse in">
{% if (req.getBody()|length < 1) %}
<div class="blankslate blankslate-sm">
<h3>Empty body</h3>
</div>
{% else %}
<pre>{{ req.getBody() }}</pre>
{% endif %}
</div>
</div>
</div>
</div>
{% else %}
<div class="blankslate">
<h3>No requests made yet.</h3>
<p>No http requests has been made to this callback.</p>
</div>
{% endfor %}
</div>
<nav class="text-center" aria-label="Page navigation">
{{ partial('pagination') }}
</nav>
</div>

View file

@ -0,0 +1,8 @@
<span class="text-center">
<h1>An Error Occurred!</h1>
<p>The server freaked out while computing the bits. Try again later.</p>
<p>If the problem persist, contact <a href="mailto:henrik.hautakoski@gmail.com">this guy</a></p>
</span>

View file

@ -0,0 +1,11 @@
{% set google_url = "http://google.com?q=" ~ url | escape %}
<span class="text-center">
<h1>404 Not Found</h1>
<p>
This page does not exist! You can search for it on
<a target="_blank" href="{{ google_url }}">google</a>
if you want.
</p>
</span>

View file

@ -0,0 +1,64 @@
<div class="about">
<div class="about-main">
<div class="section">
<div class="section-header">
<h1>About</h1>
</div>
<p>
httpcb was created because I needed to debug some API's with
the callback concept over the years (The problem is you can't call
your local webserver most of the time because it's behind NAT and
your development server is not configured to handle public traffic etc.)
</p>
<p>
There is ofcourse alot of similar applications out there
(alot of people run into the <i>"local dev server"</i>-problem).
However. They where mostly annoying with trail periods, super
advanced UI and limited amount of requests. etc. So i decided to
make my own.
</p>
<p>
Later this project evolved to be my
<i>"try that new thing"</i>-project.
So now, it serves as both a quick tool to check the HTTP request
some API will send you and a place where i can try out new web technologies.
And because the whole point of this application is that it's on a public webserver.
Why not let others use it if they want!
</p>
<p>
So if you want you can send me a <a href="mailto:henrik.hautakoski@gmail.com">email</a>
if you find a bug, request som future or just to let me know that i helped someone with debugging.
</p>
</div>
</div>
<div class="about-reference">
<div class="section">
<h4 class="text-center">Built with</h4>
<div class="phalcon">
<a target="_blank" href="http://phalconphp.com">
<img class="img-responsive" src="/img/phalcon-php.png" />
</a>
</div>
<br/>
<div class="text-center">
<a target="_blank" href="http://getbootstrap.com">
<img height="40" src="/img/bootstrap-solid.svg" />
Bootstrap
</a>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,32 @@
<div class="feature-section">
<div class="section-header">
<h1>How Does It Work?</h1>
</div>
<div class="steps">
<div class="steps-step1">
<div class="steps-img"></div>
<h3>1. Create a new Callback</h3>
<p>Register a callback and you will be given a unique url</p>
</div>
<div class="steps-step2">
<div class="steps-img"></div>
<h3>2. Set endpoint URL</h3>
<p>Configure your API that you want to test to send to that url</p>
</div>
<div class="steps-step3">
<div class="steps-img"></div>
<h3>3. Monitor traffic</h3>
<p>Make API Calls and watch what your API will send you</p>
</div>
</div>
<div class="text-center">
<a href="/callback/new" class="button button-large button-brand">Get started</a>
</div>
</div>

View file

@ -0,0 +1,31 @@
<div class="section">
<h3>Activity Log</h3>
<table class="table table-condensed table-striped table-hover">
<thead>
<tr>
<th>Date</th>
<th>Ip</th>
<th>Message</th>
</tr>
</thead>
<tbody>
{% for item in page.items %}
<tr>
<td>{{ item.getTimestamp() }}</td>
<td>{{ item.getIp() }}</td>
<td>{{ item.getMessage() }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<nav class="text-center" aria-label="Page navigation">
{{ partial('pagination') }}
</nav>
</div>

View file

@ -0,0 +1,116 @@
{%
set social_links = [
'github' : [ 'connected': user.getGithubId() > 0 ],
'gitlab' : [ 'connected': user.getGitlabId() > 0, 'class': 'text-gitlab' ],
'google' : [ 'connected': user.getGoogleId() > 0, 'class': 'text-google' ],
'linkedin' : [ 'connected': user.getLinkedinId() | length, 'class': 'text-linkedin' ]
]
%}
<div class="section">
<form class="form-horizontal" method="post" action="">
<div class="form-group">
{{ form.renderDecorated('username', [ 'length': 7 ]) }}
{{ form.renderDecorated('id', [ 'length': 2, 'label-length' : 1 ]) }}
</div>
<div class="form-group">
{{ form.renderDecorated('name') }}
</div>
<div class="form-group">
{{ form.renderDecorated('email') }}
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<h4>Password</h4>
</div>
</div>
{% if form.has('passwordCurrent') %}
<div class="form-group">
{{ form.renderDecorated('passwordCurrent') }}
</div>
{% endif %}
<div class="form-group">
{{ form.renderDecorated('passwordNew') }}
</div>
<div class="form-group">
{{ form.renderDecorated('passwordConfirm') }}
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<h4>Social sign-in</h4>
<hr />
{% for name,info in social_links %}
<div class="col-sm-2 text-center">
{% set class = info['class'] | default(false) %}
<div{{ class ? ' class="%s"'|format(class) : '' }}>{{ icon('brand/' ~ name, [ '3x' ]) }}</div>
{% if info['connected'] %}
<a href="{{ url(['for': 'oauth-disconnect', 'provider': name]) }}">Disconnect</a>
{% else %}
<a href="{{ url(['for': 'oauth', 'strategy': name]) }}">Connect</a>
{% endif %}
</div>
{% endfor %}
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<hr />
{{ form.render('Save') }}
<button class="button button-danger pull-right" type="button" data-toggle="modal" data-target="#deleteModal">
Delete Account
</button>
</div>
</div>
</form>
</div>
<div class="modal fade" id="deleteModal" tabindex="-1" role="dialog" aria-labelledby="deleteModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title pull-left" id="deleteModalLabel">Delete account</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<form method="post" action="/user/delete">
<div class="modal-body">
<p>
Deleting your account is a non-reversible action.
All data associated with your account will be lost in the process.
</p>
{% if user.password|length > 0 %}
<p>Enter your <kbd>password</kbd> to confirm:</p>
<input type="password" name="currentpw" class="form-control" />
{% endif %}
</div>
<div class="modal-footer">
<button type="button" class="button button-default" data-dismiss="modal">Close</button>
<input type="submit" name="deleteAcc" class="button button-danger" value="Delete account">
</div>
</form>
</div>
</div>
</div>