Make UserState roles immutable
[aquarium] / src / main / scala / gr / grnet / aquarium / logic / events / UserEvent.scala
1 package gr.grnet.aquarium.logic.events
2
3 import gr.grnet.aquarium.util.json.JsonHelpers
4 import net.liftweb.json.{Extraction, parse => parseJson}
5 import gr.grnet.aquarium.Configurator._
6 import com.ckkloverdos.maybe.{Failed, NoVal, Just}
7
8 /**
9  * Represents an incoming user event.
10  *
11  * @author Georgios Gousios <gousiosg@gmail.com>
12  */
13 case class  UserEvent(
14     override val id: String,           // The id at the client side (the sender) TODO: Rename to remoteId or something...
15     override val occurredMillis: Long, // When it occurred at client side (the sender)
16     override val receivedMillis: Long, // When it was received by Aquarium
17     userId: String,
18     eventVersion: Short,
19     eventType: Short, //1: create, 2: modify
20     state: String,    //ACTIVE, SUSPENDED
21     idp: String,
22     tenant: String,
23     roles: List[String])
24   extends AquariumEvent(id, occurredMillis, receivedMillis) {
25
26   assert(eventType == 1 || eventType == 2)
27   assert(state.equalsIgnoreCase("ACTIVE") ||
28     state.equalsIgnoreCase("SUSPENDED"))
29
30   if (eventType == 1)
31     if(!state.equalsIgnoreCase("ACTIVE"))
32       assert(false)
33
34   /**
35    * Validate this event according to the following rules:
36    *
37    * Valid event states: `(eventType, state)`:
38    *  - `a := 1, ACTIVE`
39    *  - `b := 2, ACTIVE`
40    *  - `c := 2, SUSPENDED`
41    *
42    * Valid transitions:
43    *  - `(non-existent) -> a`
44    *  - `a -> c`
45    *  - `c -> b`
46    */
47   def validate: Boolean = {
48
49     MasterConfigurator.userStateStore.findUserStateByUserId(userId) match {
50       case Just(x) =>
51         if (eventType == 1){
52           logger.warn("User to create exists: IMEvent".format(this.toJson));
53           return false
54         }
55       case NoVal =>
56         if (eventType != 2){
57           logger.warn("Inexistent user to modify. IMEvent:".format(this.toJson))
58           return false
59         }
60       case Failed(x,y) =>
61         logger.warn("Error retrieving user state: %s".format(x))
62     }
63
64     true
65   }
66
67   def setRcvMillis(millis: Long) = copy(receivedMillis = millis)
68
69   def isCreateUser = eventType == 1
70
71   def isModifyUser = eventType == 2
72
73   def isStateActive = state equalsIgnoreCase "ACTIVE"
74
75   def isStateSuspended =  state equalsIgnoreCase "SUSPENDED"
76 }
77
78 object UserEvent {
79   def fromJson(json: String): UserEvent = {
80     implicit val formats = JsonHelpers.DefaultJsonFormats
81     val jsonAST = parseJson(json)
82     Extraction.extract[UserEvent](jsonAST)
83   }
84
85   def fromBytes(bytes: Array[Byte]): UserEvent = {
86     JsonHelpers.jsonBytesToObject[UserEvent](bytes)
87   }
88 }