start on access requests

This commit is contained in:
Connor Turland 2016-10-13 22:34:58 -04:00
parent fc2849824f
commit 8d6ae2321c
17 changed files with 306 additions and 32 deletions

View file

@ -0,0 +1,43 @@
.request_access {
position: absolute;
width: 90%;
margin: 0 5%;
.monkey {
width: 250px;
height: 250px;
border: 6px solid #424242;
border-radius: 125px;
background: url(https://s3.amazonaws.com/metamaps-assets/site/monkeyselfie.jpg) no-repeat;
background-position: 50% 20%;
background-size: 100%;
margin: 80px auto 20px auto;
}
.explainer_text {
padding: 0 20% 0 20%;
font-size: 24px;
line-height: 30px;
margin-bottom: 20px;
text-align: center;
}
.make_request {
background-color: #a354cd;
display: block;
width: 220px;
height: 14px;
padding: 16px 0;
margin-bottom: 16px;
text-align: center;
border-radius: 2px;
font-size: 14px;
box-shadow: 0px 1px 1.5px rgba(0,0,0,0.12), 0 1px 1px rgba(0,0,0,0.24);
margin: 0 auto 20px auto;
text-decoration: none;
color: #FFFFFF !important;
cursor: pointer;
}
}

View file

@ -22,21 +22,26 @@ class ApplicationController < ActionController::Base
helper_method :admin?
def after_sign_in_path_for(resource)
sign_in_url = url_for(action: 'new', controller: 'sessions', only_path: false)
sign_in_url = new_user_session_url
sign_up_url = new_user_registration_url
stored = stored_location_for(User)
if request.referer == sign_in_url
if stored
stored
elsif request.referer.include?(sign_in_url) || request.referer.include?(sign_up_url)
super
elsif params[:uv_login] == '1'
'http://support.metamaps.cc/login_success?sso=' + current_sso_token
else
stored_location_for(resource) || request.referer || root_path
request.referer || root_path
end
end
def handle_unauthorized
if authenticated?
if authenticated? and params[:controller] == 'maps' and params[:action] == 'show'
redirect_to request_access_map_path(params[:id])
elsif authenticated?
redirect_to root_path, notice: "You don't have permission to see that page."
else
store_location_for(resource, request.fullpath)
redirect_to new_user_session_path, notice: 'Try signing in to do that.'
end
end

View file

@ -1,8 +1,9 @@
# frozen_string_literal: true
class MapsController < ApplicationController
before_action :require_user, only: [:create, :update, :destroy, :access, :events]
before_action :set_map, only: [:show, :update, :destroy, :access, :contains,
:events, :export]
before_action :set_map, only: [:show, :request_access, :update, :destroy, :access, :contains,
:events, :export, :access_request, :approve_access, :deny_access, :approve_access_post,
:deny_access_post]
after_action :verify_authorized
# GET maps/:id
@ -22,6 +23,11 @@ class MapsController < ApplicationController
end
end
# GET maps/:id/request_access
def request_access
@map = nil
end
# GET maps/new
def new
@map = Map.new(name: 'Untitled Map', permission: 'public', arranged: true)
@ -80,6 +86,19 @@ class MapsController < ApplicationController
end
end
# POST maps/:id/access_request
def access_request
request = AccessRequest.create(user: current_user, map: @map)
# what about push notification to map owner?
MapMailer.access_request_email(request, @map).deliver_later
respond_to do |format|
format.json do
head :ok
end
end
end
# POST maps/:id/access
def access
user_ids = params[:access] || []
@ -93,7 +112,7 @@ class MapsController < ApplicationController
respond_to do |format|
format.json do
render json: { message: 'Successfully altered edit permissions' }
head :ok
end
end
end
@ -133,6 +152,48 @@ class MapsController < ApplicationController
end
end
# GET maps/:id/approve_access/:request_id
def approve_access
request = AccessRequest.find_by_id(params[:request_id])
request.approve() if request
respond_to do |format|
format.html { redirect_to map_path(@map), notice: request ? 'Request was approved' : 'No request there to approve' }
end
end
# GET maps/:id/deny_access/:request_id
def deny_access
request = AccessRequest.find_by_id(params[:request_id])
request.deny() if request
respond_to do |format|
format.html { redirect_to map_path(@map), notice: request ? 'Request was turned down' : 'No request there to deny' }
end
end
# POST maps/:id/approve_access/:request_id
def approve_access_post
request = AccessRequest.find_by_id(params[:request_id])
request.approve() if request
respond_to do |format|
format.json do
head :bad_request unless request
head :ok
end
end
end
# POST maps/:id/deny_access/:request_id
def deny_access_post
request = AccessRequest.find_by_id(params[:request_id])
request.deny() if request
respond_to do |format|
format.json do
head :bad_request unless request
head :ok
end
end
end
private
def set_map

View file

@ -2,19 +2,22 @@
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
before_action :configure_account_update_params, only: [:update]
after_action :store_location, only: [:new]
protected
def after_sign_up_path_for(resource)
signed_in_root_path(resource)
end
def after_update_path_for(resource)
signed_in_root_path(resource)
end
private
def store_location
if params[:redirect_to]
store_location_for(User, params[:redirect_to])
end
end
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:name, :joinedwithcode])
end

View file

@ -2,10 +2,17 @@
class MapMailer < ApplicationMailer
default from: 'team@metamaps.cc'
def access_request_email(request, map)
@request = request
@map = map
subject = @map.name + ' - request to edit'
mail(to: @map.user.email, subject: subject)
end
def invite_to_edit_email(map, inviter, invitee)
@inviter = inviter
@map = map
subject = @map.name + ' - Invitation to edit'
subject = @map.name + ' - invitation to edit'
mail(to: invitee.email, subject: subject)
end
end

View file

@ -0,0 +1,19 @@
class AccessRequest < ApplicationRecord
belongs_to :user
belongs_to :map
def approve
self.approved = true
self.answered = true
self.save
UserMap.create(user: self.user, map: self.map)
# send an email and push notification here?
end
def deny
self.approved = false
self.answered = true
self.save
# send an email and push notification here?
end
end

View file

@ -9,6 +9,7 @@ class Map < ApplicationRecord
has_many :messages, as: :resource, dependent: :destroy
has_many :stars
has_many :access_requests, dependent: :destroy
has_many :user_maps, dependent: :destroy
has_many :collaborators, through: :user_maps, source: :user

View file

@ -37,10 +37,36 @@ class MapPolicy < ApplicationPolicy
end
def access?
# note that this is to edit who can access the map
# this is for the map creator to bulk change who can access the map
user.present? && record.user == user
end
def request_access?
# this is to access the page where you can request access to a map
user.present?
end
def access_request?
# this is to actually request access
user.present?
end
def approve_access?
record.user == user
end
def deny_access?
approve_access?
end
def approve_access_post?
approve_access?
end
def deny_access_post?
approve_access?
end
def contains?
show?
end

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body style="font-family: sans-serif; width: 100%; padding: 24px 16px 16px 16px; background-color: #f5f5f5; text-align: center;">
<div style="padding: 16px; background: white; text-align: left;">
<% button_style = "background-color:#4fc059;border-radius:2px;color:white;display:inline-block;font-family:Roboto,Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;min-height:29px;line-height:29px;min-width:54px;outline:0px;padding:0 8px;text-align:center;text-decoration:none" %>
<p><span style="font-weight: bold;"><%= @request.user.name %></span> is requesting access to <span style="font-weight: bold">collaboratively edit</span> the following metamap:</p>
<p><%= @map.name %></p>
<p><%= link_to "Grant", approve_access_map_url(id: @map.id, request_id: @request.id), target: "_blank", style: "font-size: 18px; text-decoration: none; color: #4fc059;" %>
<p><%= link_to "Deny", deny_access_map_url(id: @map.id, request_id: @request.id), target: "_blank", style: "font-size: 18px; text-decoration: none; color: #DB5D5D;" %></p>
<%= link_to 'Open in Metamaps', map_url(@map), target: "_blank", style: button_style %>
<p style="font-size: 12px;">Make sense with Metamaps</p>
</div>
</body>
</html>

View file

@ -0,0 +1,10 @@
<%= @request.user.name %> has requested to collaboratively edit the following metamap:
<%= @map.name %> [<%= map_url(@map) %>]
Approve Request [<%= approve_access_map_url(id: @map.id, request_id: @request.id) %>]
Deny Request [<%= deny_access_map_url(id: @map.id, request_id: @request.id) %>]
Make sense with Metamaps

View file

@ -0,0 +1,35 @@
<%#
# @file
# Code to request access to a map
# /maps/:id/request_access
#%>
<% content_for :title, 'Request Access | Metamaps' %>
<% content_for :mobile_title, 'Request Access' %>
<div class='request_access'>
<div class='monkey'></div>
<div class='explainer_text'>
Oops! This map is private, but you can request<br> to edit it from the map creator.
</div>
<div class='make_request'>REQUEST ACCESS</div>
</div>
<script>
$(document).ready(function() {
$('.make_request').click(function() {
var that = $(this)
that.off('click')
that.text('requesting...')
$.ajax({
url: '/maps/<%= params[:id] %>/access_request',
type: 'POST',
contentType: 'application/json',
statusCode: {
200: function () { that.text('Request Sent!'); setTimeout(function () {window.location.href = '/'}, 2000) },
500: function () { that.text('An error occurred') }
}
})
})
})
</script>

View file

@ -32,7 +32,7 @@ Rails.application.configure do
# Print deprecation notices to the Rails logger
config.active_support.deprecation = :log
config.action_mailer.preview_path = '/vagrant/spec/mailers/previews'
config.action_mailer.preview_path = "#{Rails.root}/spec/mailers/previews"
# Expands the lines which load the assets
config.assets.debug = false

View file

@ -16,12 +16,18 @@ Metamaps::Application.routes.draw do
resources :maps, except: [:index, :edit] do
member do
get :request_access
get 'approve_access/:request_id', action: :approve_access, as: :approve_access
get 'deny_access/:request_id', action: :deny_access, as: :deny_access
get :export
post 'events/:event', action: :events
get :contains
post :access_request, default: { format: :json }
post 'approve_access/:request_id', action: :approve_access_post, default: { format: :json }
post 'deny_access/:request_id', action: :deny_access_post, default: { format: :json }
post :access, default: { format: :json }
post :star, to: 'stars#create', defaults: { format: :json }
post :unstar, to: 'stars#destroy', defaults: { format: :json }
post :star, to: 'stars#create', default: { format: :json }
post :unstar, to: 'stars#destroy', default: { format: :json }
end
end
@ -54,6 +60,19 @@ Metamaps::Application.routes.draw do
end
end
devise_for :users, skip: :sessions, controllers: {
registrations: 'users/registrations',
passwords: 'users/passwords',
sessions: 'devise/sessions'
}
devise_scope :user do
get 'login' => 'devise/sessions#new', :as => :new_user_session
post 'login' => 'devise/sessions#create', :as => :user_session
get 'logout' => 'devise/sessions#destroy', :as => :destroy_user_session
get 'join' => 'devise/registrations#new', :as => :new_user_registration_path
end
resources :users, except: [:index, :destroy] do
member do
get :details
@ -84,19 +103,6 @@ Metamaps::Application.routes.draw do
match '*path', to: 'v2/restful#catch_404', via: :all
end
devise_for :users, skip: :sessions, controllers: {
registrations: 'users/registrations',
passwords: 'users/passwords',
sessions: 'devise/sessions'
}
devise_scope :user do
get 'login' => 'devise/sessions#new', :as => :new_user_session
post 'login' => 'devise/sessions#create', :as => :user_session
get 'logout' => 'devise/sessions#destroy', :as => :destroy_user_session
get 'join' => 'devise/registrations#new', :as => :new_user_registration_path
end
namespace :hacks do
get 'load_url_title'
end

View file

@ -0,0 +1,12 @@
class CreateAccessRequests < ActiveRecord::Migration[5.0]
def change
create_table :access_requests do |t|
t.references :user, foreign_key: true
t.boolean :approved
t.boolean :answered
t.references :map, foreign_key: true
t.timestamps
end
end
end

View file

@ -10,11 +10,22 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160928022635) do
ActiveRecord::Schema.define(version: 20161013162214) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "access_requests", force: :cascade do |t|
t.integer "user_id"
t.boolean "approved"
t.boolean "answered"
t.integer "map_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["map_id"], name: "index_access_requests_on_map_id", using: :btree
t.index ["user_id"], name: "index_access_requests_on_user_id", using: :btree
end
create_table "delayed_jobs", force: :cascade do |t|
t.integer "priority", default: 0, null: false
t.integer "attempts", default: 0, null: false
@ -268,5 +279,7 @@ ActiveRecord::Schema.define(version: 20160928022635) do
t.index ["hookable_type", "hookable_id"], name: "index_webhooks_on_hookable_type_and_hookable_id", using: :btree
end
add_foreign_key "access_requests", "maps"
add_foreign_key "access_requests", "users"
add_foreign_key "tokens", "users"
end

View file

@ -4,4 +4,9 @@ class MapMailerPreview < ActionMailer::Preview
def invite_to_edit_email
MapMailer.invite_to_edit_email(Map.first, User.first, User.second)
end
def access_request_email
request = AccessRequest.first
MapMailer.access_request_email(request, request.map)
end
end

View file

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe AccessRequest, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end