예제 #1
0
 public PermissionLevel(PermLevel Level) => this.Level = Level;
예제 #2
0
        public void ProcessEndpoint(Type T, ContextProvider Context)
        {
            RequestProvider  Request  = Context.Request;
            ResponseProvider Response = Context.Response;

            //Create an instance of the specified endpoint and set the required values.
            //We're not using a constructor because it would require each individual endpoint to have its own constructor that just calls the base APIEndpoint constructor, and that's a pain.
            APIEndpoint Endpoint = (APIEndpoint)Activator.CreateInstance(T);

            Endpoint.Connection = Connection;
            Endpoint.Context    = Context;
            Endpoint.Response   = Context.Response;
            Endpoint.Request    = Context.Request;
            Endpoint.Params     = Context.Request.Params;

            //Set access control headers for CORS support.
            List <string> AllowedMethods = new List <string>();

            foreach (MethodInfo M in T.GetMethods())
            {
                if (M.DeclaringType == GetType())
                {
                    AllowedMethods.Add(M.Name);
                }
            }

            bool OriginHeader = Request.Headers.TryGetValue("origin", out List <string> Origins);

            if (OriginHeader && Program.CORSAddresses.Contains(Origins[0] + '/'))
            {
                Response.Headers.Add("Access-Control-Allow-Origin", Origins[0]);
            }
            Response.Headers.Add("Allow", string.Join(", ", AllowedMethods));
            Response.Headers.Add("Access-Control-Allow-Headers", "Content-Type");

            // Get the endpoint method
            MethodInfo Method = Endpoint.GetType().GetMethod(Request.HttpMethod.ToString());

            //Check this method's required content type, if any.
            RequireContentType CT = Method.GetCustomAttribute <RequireContentType>();

            if (CT != null)
            {
                if (CT.ContentType == "application/json")
                {
                    //Try to parse the JSON. If that failed for some reason, check if the response body is actually necessary.
                    //Return null if it isn't, return a 400 Bad Request if it is.
                    using StreamReader Reader = new StreamReader(Request.InputStream, Request.ContentEncoding);
                    string JSONText = Reader.ReadToEnd();
                    try {
                        Endpoint.JSON = JObject.Parse(JSONText);
                    } catch (JsonReaderException e) {
                        if (Method.GetCustomAttribute <RequireBody>() != null)
                        {
                            Log.Warning("Refused request for endpoint " + T.Name + ": Could not parse JSON");
                            Log.Debug("Message: " + e.Message);
                            Log.Debug("Received JSON: " + JSONText);
                            Response.Send("Invalid JSON: " + e.Message, HttpStatusCode.BadRequest);
                            return;
                        }
                        Endpoint.JSON = null;
                    }
                }
            }

            //Check whether the user is allowed to use this endpoint method, if necessary.
            #region PermissionLevel Attribute
            PermissionLevel Attr = Method.GetCustomAttribute <PermissionLevel>();
            if (Attr != null)
            {
                //Check cookie. If its missing, send a 401 Unauthorized if the cookie is missing. (because a user MUST be logged in to use an endpoint with a PermissionLevel attribute)
                Cookie SessionIDCookie = Request.Cookies["SessionID"];
                if (SessionIDCookie == null)
                {
                    Response.Send("No Session", HttpStatusCode.Unauthorized);
                    return;
                }

                //Check if a session exists with the Session ID contained in the session cookie. If none is found or the session has expired, send back a 401 Unauthorized
                Session s = Session.GetUserSession(Connection, SessionIDCookie.Value);
                if (s == null)
                {
                    Response.Send("Expired session", HttpStatusCode.Unauthorized);
                    return;
                }
                //Renew the session, and save it in the endpoint object.
                s.Renew(Connection);
                Endpoint.UserSession = s;

                //Save user in endpoint object
                Endpoint.RequestUser = Connection.Get <User>(s.User);

                //Get department name. If none was found, assume Administrators
                string DepartmentName;
                if (Endpoint.Params.ContainsKey("Department"))
                {
                    DepartmentName = Endpoint.Params["Department"][0];
                }
                else
                {
                    DepartmentName = "Administrators";
                }

                //Get department. If none was found, send 400 Bad Request
                Department Dept = Department.GetByName(Connection, DepartmentName);
                if (Dept == null)
                {
                    Response.Send("No such Department", HttpStatusCode.BadRequest);
                    return;
                }

                //Get permissionlevel
                PermLevel Level = Endpoint.RequestUser.GetPermissionLevel(Connection, Dept.ID);
                Endpoint.RequestUserLevel = Level;

                //Check permission level
                if (Level < Attr.Level)
                {
                    Log.Warning("User " + Endpoint.RequestUser.Email + " attempted to access endpoint " + T.Name + " without sufficient permissions");
                    Log.Warning("Department: '" + DepartmentName + "', User is '" + Level + "' but must be at least '" + Attr.Level + "'");
                    Response.Send(HttpStatusCode.Forbidden);
                    return;
                }
            }
            #endregion

            //Attempt to invoke the API endpoint method. If this fails, send a 500 Internal Server Error to the client.
            try {
                Method.Invoke(Endpoint, null);
            } catch (Exception e) {
                Log.Error("Failed to fullfill request for endpoint " + T.Name + ": " + e.GetType().Name + ", " + e.Message);
                Response.Send(Utils.GetErrorPage(HttpStatusCode.InternalServerError, e.Message), HttpStatusCode.InternalServerError);
            }
        }
예제 #3
0
        public async Task HandleCommand(ICommandContext context)
        {
            try
            {
                string[]   args = context.Message.Content.Split(' ');
                IGuildUser user = (IGuildUser)context.Message.Author;
                if (context.Message.Content.StartsWith(context.Guild.EveryoneRole.Mention))
                {
                    await context.Channel.SendMessageAsync("You cannot mention everyone in a command.");

                    return;
                }

                args[0] = args[0].Replace(Program.Config.BotPrefix, "");

                switch (args[0].ToLower())
                {
                case "ping":
                    await context.Channel.SendMessageAsync($"Pong!");

                    return;

                case "addusr":
                {
                    if (user.RoleIds.All(r => r != Program.Config.StaffRoleId))
                    {
                        await context.Channel.SendMessageAsync("Code 4: Permission Denied.");

                        return;
                    }

                    if (args.Length != 3)
                    {
                        await context.Channel.SendMessageAsync("Code 3: Improper number of arguments.");

                        return;
                    }

                    string id = args[1].Replace("<", "").Replace("@", "").Replace(">", "").Replace("!", "");
                    if (!ulong.TryParse(id, out ulong userId))
                    {
                        await context.Channel.SendMessageAsync($"Code 2: invalid Discord user defined.");

                        return;
                    }

                    if (!ulong.TryParse(args[2], out ulong steamId))
                    {
                        await context.Channel.SendMessageAsync("Code 5: Invalid steamID defined.");

                        return;
                    }

                    File.AppendAllText(userSync, $"{userId}:{steamId}@steam\n");
                    await context.Channel.SendMessageAsync("User successfully added to user sync file.");

                    return;
                }

                case "addrole":
                {
                    if (user.RoleIds.All(r => r != Program.Config.StaffRoleId))
                    {
                        await context.Channel.SendMessageAsync("Code 4: Permission Denied.");

                        return;
                    }

                    if (args.Length != 3)
                    {
                        await context.Channel.SendMessageAsync($"Code 3: Improper number of arguments.");

                        return;
                    }

                    string id = args[1].Replace("<", "").Replace("@", "").Replace(">", "").Replace("&", "")
                                .Replace("!", "");
                    if (!ulong.TryParse(id, out ulong roleId) || context.Guild.GetRole(roleId) == null)
                    {
                        await context.Channel.SendMessageAsync("Code 6: Unable to retrieve Discord Role.");

                        return;
                    }

                    File.AppendAllText(roleSync, $"{id}:{args[2]}");
                    await context.Channel.SendMessageAsync($"New role sync added successfully.");

                    return;
                }

                case "resync":
                {
                    await ReloadConfig();

                    await context.Channel.SendMessageAsync("Role sync configs reloaded.");

                    return;
                }

                case "delusr":
                {
                    if (user.RoleIds.All(r => r != Program.Config.StaffRoleId))
                    {
                        await context.Channel.SendMessageAsync("Code 4: Permission Denied.");

                        return;
                    }

                    if (args.Length != 2)
                    {
                        await context.Channel.SendMessageAsync("Code 3: Improper number of arguments.");

                        return;
                    }

                    string[]      readArray = File.ReadAllLines(userSync);
                    List <string> toKeep    = new List <string>();
                    foreach (string usr in readArray)
                    {
                        string[] sync = usr.Split(':');
                        if (sync[1] != $"{args[1]}@steam")
                        {
                            toKeep.Add(usr);
                        }
                    }

                    File.WriteAllLines(userSync, toKeep);
                    await context.Channel.SendMessageAsync("User sync successfully removed.");

                    return;
                }

                case "delrole":
                {
                    if (user.RoleIds.All(r => r != Program.Config.StaffRoleId))
                    {
                        await context.Channel.SendMessageAsync("Code 4: Permission Denied.");

                        return;
                    }

                    if (args.Length != 2)
                    {
                        await context.Channel.SendMessageAsync($"Code 3: Improper number of arguments.");

                        return;
                    }

                    string id = args[1].Replace("<", "").Replace("@", "").Replace(">", "").Replace("&", "")
                                .Replace("!", "");
                    if (!ulong.TryParse(id, out ulong roleId) || context.Guild.GetRole(roleId) == null)
                    {
                        await context.Channel.SendMessageAsync("Code 6: Unable to retrieve Discord Role.");

                        return;
                    }
                    string[]      readArray = File.ReadAllLines(roleSync);
                    List <string> toKeep    = new List <string>();
                    foreach (string role in readArray)
                    {
                        string[] sync = role.Split(':');
                        if (sync[0] != id)
                        {
                            toKeep.Add(role);
                        }
                    }

                    File.WriteAllLines(roleSync, toKeep);
                    await context.Channel.SendMessageAsync("Role sync successfully removed.");

                    return;
                }
                }

                if (Program.Config.AllowedCommands.ContainsKey(args[0].ToLower()))
                {
                    PermLevel lvl = PermLevel.PermLevel0;
                    foreach (ulong id in user.RoleIds.Where(s =>
                                                            s == Program.Config.PermLevel1Id || s == Program.Config.Permlevel2Id ||
                                                            s == Program.Config.Permlevel3Id || s == Program.Config.Permlevel4Id))
                    {
                        if (GetPermlevel(id) > lvl)
                        {
                            lvl = GetPermlevel(id);
                        }
                    }

                    if (lvl >= Program.Config.AllowedCommands[args[0].ToLower()])
                    {
                        ProcessSTT.SendData(context.Message.Content, Program.Config.Port,
                                            context.Message.Author.Username, context.Channel.Id);
                    }
                    else
                    {
                        await context.Channel.SendMessageAsync("Permission denied.");
                    }
                }
            }
            catch (Exception e)
            {
                Program.Error($"Command failure: {e}");
            }
        }
예제 #4
0
        public override void PATCH()
        {
            //Get required fields
            if (!Params.ContainsKey("email"))
            {
                Response.Send("Missing fields", HttpStatusCode.BadRequest);
                return;
            }

            //Administrator account can't be modified;
            if (Params["email"][0] == "Administrator")
            {
                Response.Send(HttpStatusCode.Forbidden);
                return;
            }

            //Check if the specified user exists. If it doesn't, send a 404 Not Found
            User Acc = User.GetUserByEmail(Connection, Params["email"][0]);

            if (Acc == null)
            {
                Response.Send("No such user", HttpStatusCode.NotFound);
                return;
            }

            //Change email if necessary
            if (JSON.TryGetValue <string>("Email", out JToken NewEmail))
            {
                //Check if the new address is valid
                Regex rx = new Regex("^[A-z0-9]*@[A-z0-9]*.[A-z]*$");
                if (!rx.IsMatch((string)NewEmail))
                {
                    Response.Send("Invalid Email", HttpStatusCode.BadRequest);
                    return;
                }

                //Check if the new address is already in use
                if (User.GetUserByEmail(Connection, (string)NewEmail) != null)
                {
                    Response.Send("New Email already in use", HttpStatusCode.BadRequest);
                    return;
                }
                Acc.Email = (string)NewEmail;
            }

            //Change password if necessary
            if (JSON.TryGetValue <string>("Password", out JToken Password))
            {
                Regex PasswordRx = new Regex((string)Config.GetValue("AuthenticationSettings.PasswordRegex"));
                if (!PasswordRx.IsMatch((string)Password) || ((string)Password).Length == 0)
                {
                    Response.Send("Password does not meet requirements", HttpStatusCode.BadRequest);
                    return;
                }
                Acc.ChangePassword(Connection, (string)Password);
            }

            //Set department permissions if necessary
            if (JSON.TryGetValue <JObject>("MemberDepartments", out JToken MemberDepartment))
            {
                JObject Perms = (JObject)MemberDepartment;
                foreach (KeyValuePair <string, JToken> Entry in Perms)
                {
                    //Check if the specified department exists, skip if it doesn't.
                    Department Dept = Department.GetByName(Connection, Entry.Key);
                    if (Dept == null)
                    {
                        continue;
                    }
                    //Check if the specified account type is valid. If it isn't, skip it.
                    if (!PermLevel.TryParse((string)Entry.Value, out PermLevel Level))
                    {
                        continue;
                    }
                    //If the new user has a greater perm than the requestuser, skip it.
                    if (Level > RequestUserLevel)
                    {
                        continue;
                    }

                    //Set level
                    Acc.SetPermissionLevel(Connection, Level, Dept);
                }
            }

            //Set optional fields
            foreach (var x in JSON)
            {
                if (x.Key == "Email" || x.Key == "PasswordHash")
                {
                    continue;
                }
                PropertyInfo Prop = Acc.GetType().GetProperty(x.Key);
                if (Prop == null)
                {
                    continue;
                }
                dynamic Value = x.Value.ToObject(Prop.PropertyType);
                Prop.SetValue(Acc, Value);
            }

            //Update DB row
            Connection.Update <User>(Acc);
            Response.Send(StatusCode: HttpStatusCode.OK);
        }
예제 #5
0
 /// <summary>
 /// Sets a user permission level.
 /// </summary>
 /// <param name="Connection"></param>
 /// <param name="Level"></param>
 /// <param name="Department"></param>
 public void SetPermissionLevel(SQLiteConnection Connection, PermLevel Level, int Department) => Connection.Execute("INSERT OR REPLACE INTO Permissions (User, Permission, Department) VALUES (@User, @Permission, @Department)", new { user = this.ID, Permission = Level, Department });
예제 #6
0
 /// <summary>
 /// Sets a user permission level.
 /// </summary>
 /// <param name="Connection"></param>
 /// <param name="Level"></param>
 /// <param name="Department"></param>
 public void SetPermissionLevel(SQLiteConnection Connection, PermLevel Level, Department Department) => SetPermissionLevel(Connection, Level, Department.ID);