ctf-server

old server for hosting capture-the-flag

git clone https://9o.is/git/ctf-server.git

Flag.scala

(2766B)


      1 package com.jcabrra
      2 package model
      3 
      4 import net.liftweb._
      5 import mapper._
      6 import util.Helpers._
      7 
      8 class Flag extends LongKeyedMapper[Flag] with IdPK with ManyToMany {
      9   def getSingleton = Flag
     10 
     11   /* The challenge this flag belongs to. */
     12   object challenge extends MappedLongForeignKey(this, Challenge)
     13 
     14   /* They key, the string that needs to be captured from the GPS location. */
     15   object key extends MappedLong(this)
     16 
     17   /* The flag/answer. */
     18   object answer extends MappedLong(this)
     19   
     20   /* Capturing this flag leads you to the end/win/prize/game over */
     21   object winner extends MappedBoolean(this)
     22 
     23   /* GPS coordinate of the flag. */
     24   object long extends MappedDouble(this)
     25   object lat extends MappedDouble(this)
     26 
     27   /* Users that captured this flag. */
     28   object capturedBy extends MappedManyToMany(CapturedFlags, CapturedFlags.flag, CapturedFlags.user, User)
     29 
     30   /* This challenge cannot be accessed unless a required flag has been captured. */
     31   object prerequisite extends MappedManyToMany(RequiredFlags, RequiredFlags.succeeding, RequiredFlags.preceding, Flag)
     32 
     33   def meetsPrerequisite(user: User): Boolean = {
     34     user.capturedFlags.exists(flag => prerequisite.exists(_.id == flag.id)) ||
     35       prerequisite.isEmpty
     36   }
     37 
     38   def isCorrectGuess(guess: String): Boolean = {
     39     val long = this.long.get.toString
     40     val lat = this.lat.get.toString
     41     val gps = (lat + long).filter(_.toString.matches("[0-9]"))
     42     tryo((key.get ^ gps.toLong).toString == guess) openOr false
     43   }
     44 
     45   /* Generates a nearby gps location to place this flag on the map. */
     46   def genNearbyGPS: (Double, Double) = challenge.obj.map(_.genNearbyGPS).openOr((0,0))
     47 
     48   /* If this flag was capture by a certain user. */
     49   def wasCapturedBy(user: User): Boolean = user.capturedFlags.exists(_.id == this.id)
     50 
     51   /* What challenges unlock after capturing this flag? */
     52   def unlocks: List[Challenge] = RequiredFlags.
     53     findAll(By(RequiredFlags.preceding, this)).
     54     flatMap(_.succeeding.obj).
     55     flatMap(_.challenge.obj)
     56 }
     57 
     58 object Flag extends Flag with LongKeyedMetaMapper[Flag]
     59 
     60 /*
     61  Join Table for captured flags.
     62 */
     63 object CapturedFlags extends CapturedFlags with LongKeyedMetaMapper[CapturedFlags]
     64 
     65 class CapturedFlags extends LongKeyedMapper[CapturedFlags] with IdPK {
     66   def getSingleton = CapturedFlags
     67   object user extends MappedLongForeignKey(this, User)
     68   object flag extends MappedLongForeignKey(this, Flag)
     69 }
     70 
     71 /*
     72  Join Table for required flags. Creates a "chain".
     73 */
     74 object RequiredFlags extends RequiredFlags with LongKeyedMetaMapper[RequiredFlags]
     75 
     76 class RequiredFlags extends LongKeyedMapper[RequiredFlags] with IdPK {
     77   def getSingleton = RequiredFlags
     78   object preceding extends MappedLongForeignKey(this, Flag)
     79   object succeeding extends MappedLongForeignKey(this, Flag)
     80 }