Skip to content
This repository has been archived by the owner on May 2, 2024. It is now read-only.

Commit

Permalink
Provisional Apps
Browse files Browse the repository at this point in the history
  • Loading branch information
reesericci committed Jan 24, 2024
1 parent 2cd04f6 commit a870ba3
Show file tree
Hide file tree
Showing 24 changed files with 506 additions and 61 deletions.
Binary file added app/assets/images/oblong-dev.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 16 additions & 1 deletion app/controllers/admin_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ def domains
end

def review
@domains = Domain.where(provisional: true).map { |d| {domain_id: d.id, host: d.host, plan: d.plan} }
@domains = Domain.where(provisional: true).map { |d| {resource_id: d.id, name: d.host, plan: d.plan} }
end

def developers_review
@apps = Doorkeeper::Application.where(provisional: true).map { |d| {resource_id: d.id, name: d.name, plan: d.plan, uri: d.redirect_uri} }
end

def review_decision
Expand All @@ -32,6 +36,17 @@ def review_decision
end
end

def developers_review_decision
app = Doorkeeper::Application.find_by(id: params[:application_id])

if params[:provisional_action] == "accept"
app.update!(provisional: false)
Developers::ApplicationMailer.with(email: User::User.find_by(id: app.owner_id).email, app: app.name).domain_created_email.deliver_later
elsif params[:provisional_action] == "reject"
app.destroy!
end
end

private

def require_admin
Expand Down
9 changes: 8 additions & 1 deletion app/controllers/api/v1/api_controller.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
class Api::V1::ApiController < ActionController::Base

Check failure on line 1 in app/controllers/api/v1/api_controller.rb

View workflow job for this annotation

GitHub Actions / StandardRB

app/controllers/api/v1/api_controller.rb#L1

Controllers should subclass `ApplicationController`.

skip_before_action :verify_authenticity_token

before_action :not_provisional

private

# Find the user that owns the access token
def current_user
User::User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
end

def not_provisional
if Doorkeeper::Application.find_by(id: doorkeeper_token.application_id).provisional?
render plain: "425 Too Early - Provisional Client", status: 425
end
end
end
107 changes: 105 additions & 2 deletions app/controllers/developers/applications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,120 @@ class Developers::ApplicationsController < ApplicationController
@developers = true
end

before_action except: [:index, :request, :provision, :create] do
if (current_application.provisional? || current_application.owner_id != current_user.id) && !current_user.admin?
render plain: "403 Forbidden or Provisional Domain", status: 403
end
end

before_action only: [:create] do
if !current_user.admin?
render plain: "403 Forbidden", status: 403
end
end

def index
@user = current_user
@applications = current_user.oauth_applications
end

def show
@application = Doorkeeper::Application.find_by(id: params[:id])
@application = current_application
end

def add_scope
@application = Doorkeeper::Application.find_by(id: params[:id])
@application = current_application
@application.update!(scopes: Doorkeeper::OAuth::Scopes.from_array([@application.scopes, params[:scope]]))
redirect_back(fallback_location: developers_applications_path(id: params[:id]))
end

def destroy_scope
@application = current_application
scopes = @application.scopes.to_a
scopes.delete(params[:scope])
@application.update!(scopes: Doorkeeper::OAuth::Scopes.from_array(scopes))
redirect_back(fallback_location: developers_applications_path(id: params[:id]))
end

def add_redirect_uri
@application = current_application
uris = @application.redirect_uri.split("\r\n")
uris.push(params[:redirect_uri])
@application.update!(redirect_uri: uris.join("\r\n"))
redirect_back(fallback_location: developers_applications_path(id: params[:id]))
end

def destroy_redirect_uri
@application = current_application
uris = @application.redirect_uri.split("\r\n")
uris.delete(params[:redirect_uri])
@application.update!(redirect_uri: uris.join("\r\n"))
redirect_back(fallback_location: developers_applications_path(id: params[:id]))
end

def update
@application = current_application
@application.update!(name: params[:name]) if params[:name]
@application.update!(confidential: params[:confidential].to_i.zero?) if params[:confidential]
redirect_back(fallback_location: developers_applications_path(id: params[:id]))
end

def destroy
current_application.destroy!
redirect_to developers_path
end

def create
@application = Doorkeeper::Application.new(name: params[:name], redirect_uri: params[:redirect_uri], confidential: true)
@application.owner = current_user
@application.save!
redirect_to developers_application_path(id: @application.id)
end

def provision
@application = Doorkeeper::Application.new(name: params[:name], redirect_uri: params[:redirect_uri], plan: params[:plan], confidential: true, provisional: true)
@application.owner = current_user
@application.save!
redirect_to developers_path

Admin::NotifyJob.perform_later("
{
\"blocks\": [
{
\"type\": \"section\",
\"text\": {
\"type\": \"mrkdwn\",
\"text\": \"*Application request: #{@application.name}*\"
}
},
{
\"type\": \"divider\"
},
{
\"type\": \"section\",
\"text\": {
\"type\": \"mrkdwn\",
\"text\": \"*User*: #{@application.owner.name} (id: #{@application.owner.id})\n\n*Plan*: #{@application.plan}\"
},
\"accessory\": {
\"type\": \"button\",
\"text\": {
\"type\": \"plain_text\",
\"text\": \"Review Developer Apps\",
\"emoji\": true
},
\"value\": \"click_me_123\",
\"url\": \"https://admin.obl.ong/admin/developers/review\",
\"action_id\": \"button-action\"
}
}
]
}")
end

private

def current_application
Doorkeeper::Application.find_by(id: params[:id])
end
end
2 changes: 1 addition & 1 deletion app/javascript/application.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import "controllers"
import "@hotwired/turbo-rails"

import "selectlist"
14 changes: 14 additions & 0 deletions app/javascript/controllers/formselect_controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Controller } from "@hotwired/stimulus";

export default class extends Controller {
static targets = [ "select" ]

add({ formData }) {
console.log("hii")
formData.append(this.selectTarget.getAttribute("name"), this.selectTarget.value)
}

null() {
return null
}
}
14 changes: 7 additions & 7 deletions app/javascript/tinder.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ angular.module('starter', ['ionic', 'ionic.contrib.ui.tinderCards'])
$scope.cards.push(angular.extend({}, currentCard));
currentCard = null;
} else if (currentCard.action == "accept") {
document.querySelector(`form#form-${currentCard.domain_id} .action-field`).value = "accept";
document.querySelector(`form#form-${currentCard.domain_id}`).submit()
document.querySelector(`form#form-${currentCard.resource_id} .action-field`).value = "accept";
document.querySelector(`form#form-${currentCard.resource_id}`).submit()

Toastify({
text: `${currentCard.host} was accepted`,
text: `${currentCard.name} was accepted`,
duration: 3000,
newWindow: true,
close: true,
Expand All @@ -50,11 +50,11 @@ angular.module('starter', ['ionic', 'ionic.contrib.ui.tinderCards'])
}).showToast();
currentCard = null;
} else if(currentCard.action == "reject") {
document.querySelector(`form#form-${currentCard.domain_id} .action-field`).value = "reject";
document.querySelector(`form#form-${currentCard.domain_id}`).submit()
document.querySelector(`form#form-${currentCard.resource_id} .action-field`).value = "reject";
document.querySelector(`form#form-${currentCard.resource_id}`).submit()

Toastify({
text: `${currentCard.host} was rejected`,
text: `${currentCard.name} was rejected`,
duration: 3000,
newWindow: true,
close: true,
Expand All @@ -78,7 +78,7 @@ angular.module('starter', ['ionic', 'ionic.contrib.ui.tinderCards'])

currentCard = structuredClone($scope.cards[index]);

if(window.confirm(`Are you sure you want to reject ${$scope.cards[index].host}?`)) {
if(window.confirm(`Are you sure you want to reject ${$scope.cards[index].name}?`)) {
currentCard.action = "reject"
} else {
currentCard.action = "dontDestroy"
Expand Down
6 changes: 6 additions & 0 deletions app/mailers/developers/application_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Developers::ApplicationMailer < ApplicationMailer
def app_created_email
@app = params[:domain]
mail(to: params[:email], subject: "Your app has been created!", message_stream: "outbound")
end
end
138 changes: 138 additions & 0 deletions app/views/admin/developers_review.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<main ng-app="starter" no-scroll class="admin" domains="<%= @apps.to_json %>">
<h1>Review Apps</h1>
<ion-pane ng-controller="CardsCtrl" >
<td-cards>
<td-card ng-repeat="card in cards" on-destroy="cardDestroyed($index)" on-swipe-left="cardSwipedLeft($index)" on-swipe-right="cardSwipedRight($index)" on-partial-swipe="cardPartialSwipe(amt)" class="card-{{$index}}">
<%= form_with method: :post, class: "image", "ng-controller": "CardCtrl", id: "form-{{card.resource_id}}" do |form| %>
<h2>{{card.name}}</h2>
<p><b>PLAN</b></p>
<p>{{card.plan}}</p>
<p><b>REDIRECT</b></p>
<p>{{card.uri}}</p>
<div class="no-text"></div>
<div class="yes-text"></div>
<input type="hidden" name="application_id" value="{{card.resource_id}}"/>
<input type="hidden" name="provisional_action" value="" class="action-field" />
<% end %>
</td-card>
<div class="none-left">
<h2>No more domains to review</h2>
</div>
</td-cards>
<div class="no-text">REJECT</div>
<div class="yes-text">APPROVE</div>
</ion-pane>
</main>

<% content_for :head do %>

<script src="https://code.ionicframework.com/collide/0.0.4/collide.js"></script>
<script src="https://code.ionicframework.com/1.0.0-beta.14/js/ionic.bundle.js"></script>
<script src="https://code.ionicframework.com/contrib/ionic-contrib-tinder-cards/ionic.tdcards.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/toastify-js"></script>

<%= javascript_include_tag "tinder", "data-turbo-track": "reload" %>
<% end %>

<style>
@import url("https://code.ionicframework.com/contrib/ionic-contrib-tinder-cards/ionic.tdcards.css");
@import url("https://cdn.jsdelivr.net/npm/toastify-js/src/toastify.min.css");

.pane {
background: #343434 !important;
}

td-cards {
display: block;
}

main {
width: 100%;
height: 85%;
position: relative;
color: #343434;
}

td-card {
position: absolute;
left: 50%;
margin-top: 80px;
margin-bottom: 40px;
margin-left: -150px;
width: 300px;
height: 300px;

border: 1px solid #999;
box-shadow: 0px 1px 3px rgba(0,0,0,0.2);
border-radius: 6px;
background: #F5F5F5;
color: #343434;
z-index: 1;
}

.none-left {
position: absolute;
left: 50%;
margin-top: 80px;
margin-bottom: 40px;
margin-left: -150px;
width: 300px;
height: 300px;
z-index: 0;
}

.none-left > h2 {
color: #F5F5F5;
text-align: center;
}

td-card .image {
position: relative;
padding: 1rem 1rem;
display: flex;
flex-direction: column;
gap: 0rem;
}

.yes-text {
position: absolute;
bottom: 10px;
right: 10px;
font-size: 30px;
color: #41EAD4;
text-stroke: 0.5px black;
-webkit-text-stroke: 0.5px black;
opacity: 1 !important;
}
.no-text {
position: absolute;
bottom: 10px;
left: 10px;
font-size: 30px;
color: var(--winter-sky);
opacity: 1 !important;
}

.fade {
-webkit-transition: 0.2s opacity linear;
transition: 0.2s opacity linear;
opacity: 0;
}

h1 {
font-size: 3rem;
}

h2 {
font-size: 30px;
}

.none-left > h2 {
color: var(--winter-sky);
}

form {
position: relative;
height: 100%;
}
</style>
1 change: 1 addition & 0 deletions app/views/admin/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<li><a href="/admin/users">- View Users</a></li>
<li><a href="/admin/domains">- View Domains</a></li>
<li><a href="/admin/domains/review" data-turbo="false">- Review Domain Requests</a></li>
<li><a href="/admin/developers/review" data-turbo="false">- Review Developer App Requests</a></li>
</ul>
</main>

Expand Down
Loading

0 comments on commit a870ba3

Please sign in to comment.