Slide 1

Slide 1 text

Rails Against the Machine Brittany Martin Rubyconf MY 2018 @brittjmartin

Slide 2

Slide 2 text

Lead Web Developer @ Pittsburgh Cultural Trust ARTS E- COMMERCE TEN BRANDED PATHS FESTIVAL GUIDES ALL LOVINGLY BUILT WITH RUBY @brittjmartin

Slide 3

Slide 3 text

HOSTING EMAIL PROVIDER E-COMMERCE CALL CENTER VISUAL ARTS My experience. @brittjmartin

Slide 4

Slide 4 text

Norma Skates @ Little Steel Derby Girls @brittjmartin

Slide 5

Slide 5 text

Host of the 5 by 5 Ruby on Rails Podcast @brittjmartin

Slide 6

Slide 6 text

An ideal world. @brittjmartin

Slide 7

Slide 7 text

In reality. @brittjmartin

Slide 8

Slide 8 text

Gaming the site. Milking the system. Bending the rules. @brittjmartin

Slide 9

Slide 9 text

Bad users. @brittjmartin

Slide 10

Slide 10 text

Manipulation vs. Security. Photo Credit: Moz @brittjmartin

Slide 11

Slide 11 text

Misbehaving. @brittjmartin

Slide 12

Slide 12 text

Photo Credit: NFL @brittjmartin

Slide 13

Slide 13 text

Identify. Photo Credit: Disney @brittjmartin

Slide 14

Slide 14 text

PERSONAS Ask questions. CUSTOMER SUPPORT LOGS @brittjmartin

Slide 15

Slide 15 text

“Bad user” examples. @brittjmartin Photo Credit: Dizinga

Slide 16

Slide 16 text

Photo Credit: Tone Deaf Ticket resellers. @brittjmartin

Slide 17

Slide 17 text

An American musical. $10.5m. 30 shows. @brittjmartin

Slide 18

Slide 18 text

Serial returners. @brittjmartin

Slide 19

Slide 19 text

@brittjmartin Upvote Rings

Slide 20

Slide 20 text

Profit loss. Lost relationships. Inflation. @brittjmartin

Slide 21

Slide 21 text

Strategy. @brittjmartin

Slide 22

Slide 22 text

Choice 2: Quietly degrade. Choice 1: Kick them out. @brittjmartin

Slide 23

Slide 23 text

Subtlety is key. @brittjmartin

Slide 24

Slide 24 text

Automation. @brittjmartin

Slide 25

Slide 25 text

Our tool belt. @brittjmartin

Slide 26

Slide 26 text

@brittjmartin

Slide 27

Slide 27 text

@brittjmartin Photo Credit: Choice

Slide 28

Slide 28 text

@brittjmartin

Slide 29

Slide 29 text

Define a model. @brittjmartin

Slide 30

Slide 30 text

class Reseller SAFE_STATES = %w(PA OH WV) RESELLER_CONSTITUENCY = 0 def reseller_tri_state_check(session_key) state = Address.find_billing_address(session_key).state !SAFE_STATES.include?(state) end def reseller_constituency_check(session_key, id) Rails.cache.fetch("reseller_#{session_key}", expires_in: 30.minutes) do response = TessituraRest.new.get_constituencies(id) constituency = response.map{|c| c['ConstituencyType']['Id']} constituency.include? RESELLER_CONSTITUENCY end end end

Slide 31

Slide 31 text

Mark them. @brittjmartin

Slide 32

Slide 32 text

class Reseller SAFE_STATES = %w(PA OH WV) RESELLER_CONSTITUENCY = 0 def reseller_tri_state_check(session_key) state = Address.find_billing_address(session_key).state !SAFE_STATES.include?(state) end def reseller_constituency_check(session_key, id) Rails.cache.fetch("reseller_#{session_key}", expires_in: 30.minutes) do response = TessituraRest.new.get_constituencies(id) constituency = response.map{|c| c['ConstituencyType']['Id']} constituency.include? RESELLER_CONSTITUENCY end end end

Slide 33

Slide 33 text

def authenticate_the_user authenticate_credentials do |result| result.success { remember_current_user reseller_cookie register_new_reseller head :ok } result.fail { error_message = 'The username or password entered is invalid. Please try again.' head :bad_request, :ErrorMsg => error_message } end end

Slide 34

Slide 34 text

Offload. @brittjmartin

Slide 35

Slide 35 text

class CatchNewResellerWorker include Sidekiq::Worker RESELLER_CONSTITUENCY = 223 def perform(hash) id = hash[‘id’] response = TessituraRest.new.create_constituencies(RESELLER_CONSTITUENCY, id) ResellerAlertWorker.perform_async(id: id) end end

Slide 36

Slide 36 text

class ResellerAlertWorker include Sidekiq::Worker def perform(hash={}) notification = { 'username': 'resellerbot', 'icon_emoji': ':skull:', 'fields': [ { 'title': 'Id', 'value': "#{hash['id']}" }, { 'title': 'Alert', 'value': 'Another reseller has been located and tagged!' } ] } RESELLER.ping notification end end slack- notifier.

Slide 37

Slide 37 text

No content

Slide 38

Slide 38 text

Cache the check. @brittjmartin

Slide 39

Slide 39 text

class Reseller SAFE_STATES = %w(PA OH WV) RESELLER_CONSTITUENCY = 0 def reseller_tri_state_check(session_key) state = Address.find_billing_address(session_key).state !SAFE_STATES.include?(state) end def reseller_constituency_check(session_key, id) Rails.cache.fetch("reseller_#{session_key}", expires_in: 30.minutes) do response = TessituraRest.new.get_constituencies(id) constituency = response.map{|c| c['ConstituencyType']['Id']} constituency.include? RESELLER_CONSTITUENCY end end end

Slide 40

Slide 40 text

Who’s there? @brittjmartin

Slide 41

Slide 41 text

Logged in. @brittjmartin

Slide 42

Slide 42 text

Entice them. @brittjmartin

Slide 43

Slide 43 text

Anonymous. @brittjmartin

Slide 44

Slide 44 text

C is for cookie. @brittjmartin

Slide 45

Slide 45 text

@brittjmartin Execute.

Slide 46

Slide 46 text

@brittjmartin What can we take away?

Slide 47

Slide 47 text

Select your own seat. @brittjmartin

Slide 48

Slide 48 text

@brittjmartin Print at home.

Slide 49

Slide 49 text

@brittjmartin Exchanges.

Slide 50

Slide 50 text

@brittjmartin Degrading the experience.

Slide 51

Slide 51 text

@brittjmartin

Slide 52

Slide 52 text

@brittjmartin

Slide 53

Slide 53 text

@brittjmartin

Slide 54

Slide 54 text

@brittjmartin

Slide 55

Slide 55 text

Web application firewall. @brittjmartin WAF.

Slide 56

Slide 56 text

Block, allow, count. Join & reuse. Rules. @brittjmartin

Slide 57

Slide 57 text

@brittjmartin

Slide 58

Slide 58 text

GuardDuty. @brittjmartin

Slide 59

Slide 59 text

@brittjmartin

Slide 60

Slide 60 text

@brittjmartin Remember.

Slide 61

Slide 61 text

Logo Credit: Mortal Kombat @brittjmartin

Slide 62

Slide 62 text

Photo Credit: Pittsburgh Cultural Trust @brittjmartin

Slide 63

Slide 63 text

Twitter: @brittjmartin Github: @wonderwoman13 Podcast: http://5by5.tv/rubyonrails