2 Copyright (c) 2008, 2009 Hanno Braun <hanno@habraun.net>
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
8 http://www.apache.org/licenses/LICENSE-2.0
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
19 package net
.habraun
.libcrusade
.account
.server
26 import scala
.collection
.immutable
._
31 * Creates an account. AccountManager will reply with a Boolean that indicates the success of the operation.
32 * If AccountManager replies false, this usually means that an account of that name already existed.
35 case class CreateAccount(name
: String
, password
: String
, attachment
: Any
)
40 * Deletes an account. AccountManager will reply with the deleted account, if it existed. It will reply null
44 case class DeleteAccount(name
: String
)
49 * Logs an account in. AccountManager will reply with one of the following messages: LoginSuccessful,
50 * AccountDoesNotExist, PasswordIncorrect or AccountAlreadyLoggedIn.
53 case class LoginAccount(name
: String
, password
: String
)
55 case class LoginSuccessful(account
: Account
)
56 case class AccountDoesNotExist()
57 case class PasswordIncorrect()
58 case class AccountAlreadyLoggedIn()
63 * Logs an account out. Replies with a Boolean value that indicates the success of the operation.
66 case class LogoutAccount(name
: String
)
74 class AccountManager(dataStore
: Actor
) extends Actor
{
81 loop(new HashMap
[String
, Account
])
86 private def loop(loggedInAccounts
: Map
[String
, Account
]) {
88 case CreateAccount(name
, password
, attachment
) =>
89 // Determine if the name is already taken by querying the data store for all accounts of
91 val nameTaken
= dataStore
!?
Retrieve("account." + name
) != null
93 // If the name is not taken create a new account and reply true. If it is, reply false.
95 val newAccount
= Account(name
, password
, attachment
)
96 dataStore
! Store(("account." + name
, newAccount
)::Nil
)
103 // No changes to the logged in accounts, so we'll just pass it on into the next
105 loop(loggedInAccounts
)
107 case DeleteAccount(name
) =>
108 // Tell the data store to delete the account with the given name. The store will return
109 // the account that was deleted or null if there was no account of that name.
110 val deletedAccount
= (dataStore
!?
Delete("account." + name
)).asInstanceOf
[Account
]
112 // Check if an account was deleted.
113 if (deletedAccount
== null) {
114 // No account was deleted, which means no account of that name existed. Return null.
116 loop(loggedInAccounts
)
119 // An account has been deleted. Determine if the deleted account was logged in. If it
120 // was, remove it from loggedInAccounts.
121 val newLoggedInAccounts
= {
122 if (loggedInAccounts
.contains(deletedAccount
.name
)) {
123 loggedInAccounts
- deletedAccount
.name
130 // Return the deleted account.
131 reply(deletedAccount
)
133 // Pass the new set of logged in accounts to the next loop iteration.
134 loop(newLoggedInAccounts
)
137 case LoginAccount(name
, password
) =>
138 // Retrieve the account we'd like to log in.
139 val account
= (dataStore
!?
Retrieve("account." + name
)).asInstanceOf
[Account
]
141 // Check if the account could be retrieved.
142 if (account
== null) {
143 // No account was returned, an account of that name doesn't exist.
144 reply(AccountDoesNotExist
)
145 loop(loggedInAccounts
)
148 // An account was returned. Check if the password was correct and if the account is
149 // already logged in.
150 if (account
.password
== password
) {
151 // The password is correct. Proceed with the check.
152 if (!loggedInAccounts
.contains(account
.name
)) {
153 // Account is not logged in, so it is ok to log it in.
154 reply(LoginSuccessful(account
))
155 loop(loggedInAccounts
+ (account
.name
-> account
))
158 // The account is already logged in.
159 reply(AccountAlreadyLoggedIn
)
160 loop(loggedInAccounts
)
164 // The password is incorrect.
165 reply(PasswordIncorrect
)
166 loop(loggedInAccounts
)
170 case LogoutAccount(name
) =>
171 if (loggedInAccounts
.contains(name
)) {
173 loop(loggedInAccounts
- name
)
177 loop(loggedInAccounts
)