aboutsummaryrefslogblamecommitdiffstats
path: root/server/cldb.erl
blob: 4303065143e45a4963d2334e2d28de0888e909c1 (plain) (tree)
1
2
3
4
5
6
7
8
9
                      

              
                                                                                                                                                       
                                                             
 
                                        
         
                                   
                   
                                                                         
                                          
 
                                              





                                
                
                                                                          
            
                          
 

















                                                                          
                       
 
        

                                                                         
            




                                     
                                                           


                                                       












                                                                
                                               
                
 
                   




              
                                                             














                                                 
        
 
                                               

                                 
                            













                                                              



                                                                     

                                                                

                        
                                                                                                                                


                                         
                                                            





                                       
        

                              
 
                                                                      

                                    









                                                   

                             
 
                 
                
                                                





                                               
                                          
                     

                                       
 
                 
                                                                      





                                 
                                     
                                        

                                 

                         
 
                                                   






                                     
%% The client database

-module(cldb).
-export([init/0, all/0, find/1, login/2, dec_vote/1, inc_vote/1, register/3, check_rights/1, update_votes/0, logout/1, set_client_pid/2, get_votes/1]).
-record(user, {name, passwd, votes, logged_in, pid, rights}).

%% Initialisation of the mnesia database
init() ->
    mnesia:create_schema([node()]),
    mnesia:start(),
    mnesia:create_table(user, [{attributes, record_info(fields, user)}]),
    io:format("Userdb up and running \n").

%% The basic search operations on the database
find(User) when is_list(User) ->
    find(User, '_');
find(User) ->
    find(User#user.name, '_').

find(User, Pwd) ->
    F = fun() ->
		mnesia:match_object({user, User, Pwd, '_', '_', '_', '_'})
        end,
    mnesia:transaction(F).

find_logged_in_user() ->
    F = fun() ->
		mnesia:match_object({user, '_', '_', '_', true, '_', '_'})
        end,
    case mnesia:transaction(F) of
	{atomic, List} -> {ok, List};
	_ -> {error}
    end.

find_user_by_pid(Pid) ->
    F = fun() ->
		mnesia:match_object({user, '_', '_', '_', '_', Pid, '_'})
        end,
    case mnesia:transaction(F) of
	{atomic, List} -> {ok, List};
	_ -> {error}
    end.

%% Retrieve all entries

all() ->
    F = fun() ->
		mnesia:match_object({user, '_', '_', '_', '_', '_', '_'})
        end,
    case mnesia:transaction(F) of
	{atomic, List} -> {ok, List};
	_ -> {error}
    end.

%% Perform the login operation of a user into the database.
login(User, Pwd) when is_list(User) and is_list(Pwd) ->
    case find(User, Pwd) of
	{atomic, [UserRow|_]} ->
	    %% check if user is not already logged in
	    case UserRow#user.logged_in of
		false ->
		    NewUserRow = UserRow#user{logged_in = true},
		    F = fun() ->
				mnesia:write(NewUserRow)
			end,
		    case mnesia:transaction(F) of
			{atomic, ok} ->
			    {ok, NewUserRow};
			{atomic, Why} ->
			    {error, Why}
		    end;
		_ -> {error, already_logged_in}
	    end;

	_-> {error}
    end;

login(_, _) ->
    {error}.

%% In order to log out the client after its process has died.
set_client_pid(User, Pid) ->
    case find(User) of
	{atomic, [UserRow|_]} ->
	    NewUserRow = UserRow#user{pid = Pid},
	    F = fun() ->
			mnesia:write(NewUserRow)
		end,
	    case mnesia:transaction(F) of
		{atomic, ok} ->
		    {ok, pid_updated};
		{atomic, Why} ->
		    {error, Why}
	    end;
	_ ->
	    {error, user_not_found}
    end.

%% Change the database to log out a user by PID
logout(Pid) ->
    case find_user_by_pid(Pid) of
	{ok, [UserRow|_]} ->
	    F = fun() ->
			New = UserRow#user{logged_in = false},
			mnesia:write(New)
		end,
	    case mnesia:transaction(F) of
		{atomic, ok} ->
		    {ok, logged_out};
		{atomic, Why} ->
		    {error, Why}
	    end;

	_ ->
	    {error, invalid_user}
    end.

%% Adds an entry into the database for this user.
%% If he is already registered, this will return an error.
%% In order to vote, users arer required to log in after registering.
register(User, Pwd, Root) when is_list(User) and is_list(Pwd) ->
    case find(User) of
	{atomic, []} ->
	    F = fun() ->
			mnesia:write(#user{name = User, passwd = Pwd, votes = 5, logged_in = false, pid = undef, rights = Root})
		end,
	    case mnesia:transaction(F) of
		{atomic, ok} ->
		    io:format("User created: ~s~n", [User]),
		    {ok, user_created};
		{atomic, Why} ->
		    {error, Why}
	    end;
	_ ->
	    {error, duplicated_user}
    end;
register(_,_,_) ->
    {error, invalid_username}.

%% functions to de- and increment the amount of votes a user has left.
dec_vote(User) when is_list(User) ->
    {atomic, [Head|_]} = find(User),
    if Head#user.votes > 0 ->
        F = fun() ->
                    Votes = Head#user.votes - 1,
                    New = Head#user{votes = Votes},
                    mnesia:write(New)
            end,
        mnesia:transaction(F),
        {ok};
        true -> {error}
    end;
dec_vote(User) ->
    dec_vote(User#user.name).

inc_vote(User) ->
    F = fun() ->
                {atomic, [Head|_]} = find(User),
                Votes = Head#user.votes + 1,
                New = Head#user{votes = Votes},
                mnesia:write(New)
        end,
    mnesia:transaction(F).

%% Return rights of a user (admin or nan).
check_rights(User) ->
    {atomic, [UserRow|_]} = find(User),
    UserRow#user.rights.

update_votes() ->
    %% after a song every logged in client gets one more vote to spend
    case find_logged_in_user() of
	{ok, List} ->
	    give_votes(List);
	_ -> error
    end.

%% Increment the votes of every user.
%% This is called when a song has ended.
give_votes([User|Rest]) ->
	inc_vote(User#user.name),
	give_votes(Rest);
give_votes([]) -> ok.

%% Returns the amount of votes a specific user has.
get_votes(User) ->
    case find(User) of
	{atomic, [UserRow|_]} ->
	    {ok, UserRow#user.votes};
	_ ->
	    {error, user_not_found}
    end.