As was foretold, we've added advertisements to the forums! If you have questions, or if you encounter any bugs, please visit this thread: https://forums.penny-arcade.com/discussion/240191/forum-advertisement-faq-and-reports-thread/
Options

[Programming] Kafkaesque rabbits in the queue at the pub

15859616364100

Posts

  • Options
    CampyCampy Registered User regular
    On reflection, I'm wondering if my implementation is incorrect. Specifically if my subscriber method Cooler.OnTemperatureChanged's parameters are wrong. It just seems a little... bulky to me. Like I'm not adhering to encapsulation properly by the subscriber requiring knowledge of Thermostat.TemperatureArgs subclass. I suppose I can move the TemperatureArgs class outside of the Thermostat class and that's fine...?

    Anyway if someone could sanity check me it'd be much appreciated. Trying to get my brain back into OO mode is harder than I thought!
    using System;
    
    namespace ConsoleApplication1
    {
      public class Thermostat
      {
        public class TemperatureArgs : System.EventArgs
        {
          public float NewTemperature;
    
          public TemperatureArgs( float newTemperature )
          {
            NewTemperature = newTemperature;
          }
        }
    
        public event EventHandler<TemperatureArgs> OnTemperatureChange = delegate { };
        
        public float CurrentTemperature
        {
          get { return _CurrentTemperature; }
    
          set
          {
            if (value != CurrentTemperature)
            {
              _CurrentTemperature = value;
              Console.WriteLine($"Temperature set to {value}");
              OnTemperatureChange?.Invoke(this, new TemperatureArgs(value));
            }
          }
        }
    
        private float _CurrentTemperature;
      }
    
      class Cooler
      {
        public Cooler(float temperature)
        {
          Temperature = temperature;
        }
    
        public float Temperature { get; set; }
    
        public void OnTemperatureChanged(object sender, Thermostat.TemperatureArgs tempArgs)
        {
          if (tempArgs.NewTemperature > Temperature)
          {
            System.Console.WriteLine("Cooler: On");
          }
          else
          {
            System.Console.WriteLine("Cooler: Off");
          }
        }
      }
    
      static class Program
      {
        static void Main(string[] args)
        {
          Thermostat thermostat = new Thermostat();
          Cooler cooler = new Cooler(80);
    
          thermostat.OnTemperatureChange += cooler.OnTemperatureChanged;
          Console.Write("Enter new temperature: ");
          string temperature = Console.ReadLine();
          thermostat.CurrentTemperature = int.Parse(temperature);
    
          Console.Read();  //Pause and reflect a moment...
        }
      }
    }
    

  • Options
    bowenbowen How you doin'? Registered User regular
    Looks correct to me, but I haven't compiled or tested it. You're on the right path at least.

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • Options
    urahonkyurahonky Resident FF7R hater Registered User regular
    bowen wrote: »
    Campy wrote: »
    You know those moments when you call someone over to ask about why something isn't working and then the moment you start explaining it to them you figure that shit out on your own.

    I just had the same thing but with a really long post here.

    So basically what I'm saying is thanks guys, you solved my problem by just existing!

    Also C# events are not as simple as I would have expected!

    There's an actual term for this!

    https://en.wikipedia.org/wiki/Rubber_duck_debugging

    Yeah I can't tell you how many times I wrote out a long ass post only to delete all the text because I figured it out.

  • Options
    EchoEcho ski-bap ba-dapModerator mod
    One thing I see that is apparently pretty rare is to use Funcs instead of bothering with setting up FooArgs for a delegate. Always felt really verbose to me to declare a separate type for a delegate signature when you can use a Func<foo, bar> and have it generic instead.

  • Options
    KakodaimonosKakodaimonos Code fondler Helping the 1% get richerRegistered User regular

    This... is not what I meant when I said we needed to fix the keys in the dictionary to not use doubles.
        public class MyDictionaryBecauseImStupid<TKey, TValue> : IDictionary<TKey, TValue>
        {
            private Dictionary<double, TValue> backingDictionary;
    
            public void Add(TKey key, TValue value)
            {
                double roundedKey = 0.0;
                Type objType = key.GetType();
                objType = Nullable.GetUnderlyingType(objType) ?? objType;
    
                if (objType.IsPrimitive)
                {
                    if (objType == typeof(double) || objType == typeof(float))
                    {
                        double tempKey;
                        
                        if(double.TryParse(key.ToString(), out tempKey))
                        {
                            roundedKey = Math.Round(tempKey, 2);
                            backingDictionary.Add(roundedKey, value);
                        }
                    }
                }
            }
    
        }
    
    

    Now my eye is twitching.

  • Options
    CampyCampy Registered User regular
    Could you explain more @Echo? Do you mean using an Action/Func delegate instead of the event, or somehow using them as part of the event code? I'm trying to refactor to do the latter, but not having much success!

  • Options
    SpawnbrokerSpawnbroker Registered User regular
    bowen wrote: »
    Campy wrote: »
    You know those moments when you call someone over to ask about why something isn't working and then the moment you start explaining it to them you figure that shit out on your own.

    I just had the same thing but with a really long post here.

    So basically what I'm saying is thanks guys, you solved my problem by just existing!

    Also C# events are not as simple as I would have expected!

    There's an actual term for this!

    https://en.wikipedia.org/wiki/Rubber_duck_debugging

    My coworkers think I'm crazy because I have one at my desk.

    Steam: Spawnbroker
  • Options
    OrcaOrca Also known as Espressosaurus WrexRegistered User regular
    Welp, we're past the easy bugs. I've got 3 different threading related bugs to track down.

    I'm really not looking forward to the bug that's crossing languages and kernel/user space

    Threading bugs are the worst.

  • Options
    djmitchelladjmitchella Registered User regular
    LD50 wrote: »
    Just serve a page that says "The stone age called, they want their phone back."

    Pretty close -- we just the text "Browser upgrade required" and nothing else if we know for sure it won't work. If we detect something that will still work, but might look a bit crooked in places, we show "Browser upgrade recommended", so that users at least know to expect weirdnesses.

  • Options
    djmitchelladjmitchella Registered User regular
    Quick quiz. What colour is "#8040DBFF" ?

    Is it:
    1. Opaque purple-y blue?
    or
    2. Semi-transparent light cyan?

    Answer: it depends, because WPF does ARGB and CSS does RGBA, and it took me an annoyingly long time to realise that. It doesn't help that both those colours above are "blue-ish" so both of them seemed like plausible fits for what I was seeing on screen with all the other things next to/behind/in front of it.

  • Options
    EchoEcho ski-bap ba-dapModerator mod
    Campy wrote: »
    Could you explain more @Echo? Do you mean using an Action/Func delegate instead of the event, or somehow using them as part of the event code? I'm trying to refactor to do the latter, but not having much success!

    I suppose I was speaking more about delegates than events, but since you use delegates for events... As you say, it can get really bulky. I think it's a remnant from older .NET versions where you had to do it that way, but you can get rid of a lot of that with generic Funcs now.

    I don't have time for a full explanation atm, but I did remember I had this old silly but somewhat relevant example from when I did some tutoring.

    You have a bunch of cars in a race that might explode if they go too fast. Car class looks like this:
    using System;
    
    namespace EventsDemo
    {
        class Car
        {
            static Random random = new Random();
    
            public event Action<Car> Accelerate;
            public event Action<Car> Explode;
    
            public int Position { get; set; }
            public string Make { get; set; }
            public bool IsExploded { get; set; }
    
            public void Drive()
            {
                var speed = random.Next(10, 100) + 1;
    
                if (speed > 90)
                {
                    IsExploded = true;
                    Explode?.Invoke(this);
                }
                else
                {
                    Position += speed;
                    Accelerate?.Invoke(this);
                }
            }
    
            public override string ToString()
            {
                return $"{Make} at pos {Position}, exploded: {IsExploded}";
            }
        }
    }
    

    And then this is the main race bit:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    
    namespace EventsDemo
    {
        class Program
        {
            private const int RaceLength = 300;
            private static Car winner = null;
    
            static void Main(string[] args)
            {
                var cars = new List<Car>
                {
                    new Car {Make = "Lotus"},
                    new Car {Make = "Volvo"},
                    new Car {Make = "Koenigsegg"}
                };
    
                // Register events before race
                foreach (Car car in cars)
                {
                    car.Explode += Car_Explode;
                    car.Accelerate += Car_Accelerate;
                }
    
                do
                {
                    foreach (Car car in cars)
                    {
                        if (!car.IsExploded)
                        {
                            car.Drive();
                        }
    
                        if (winner == null && car.Position >= RaceLength)
                        {
                            winner = car;
                        }
    
                        //Console.WriteLine(car);
                    }
                    Console.WriteLine();
                    Thread.Sleep(1000);
    
                } while (cars.Any(c => !c.IsExploded && c.Position < RaceLength));
    
                // Race completed
                if (winner != null)
                {
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine($"Winner: {winner.Make}!");
                    Console.ResetColor();
                }
                else
                {
                    Console.WriteLine("All cars went kaboom!");
                }
            }
    
            private static void Car_Accelerate(Car car)
            {
                Console.WriteLine($"{car.Make} accelerated to {car.Position}");
            }
    
            private static void Car_Explode(Car car)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"BOOM! {car.Make} exploded at {car.Position}!");
                Console.ResetColor();
            }
        }
    }
    

    I'm simply using an Action<Car> instead of the whole song and dance routine with writing EventHandler stuff.

  • Options
    EchoEcho ski-bap ba-dapModerator mod
    edited March 2017
    Here's a quick refactor to use an Action<float> instead of an EventHandler. Advantage of doing it this way is that there's no longer any TemperatureArgs the subscriber needs to know about, just send the new temperature.

    edit: got the Action down to one argument.
    using System;
    
    namespace ConsoleApplication1
    {
        public class Thermostat
        {
            public event Action<float> OnTemperatureChange;
    
            public float CurrentTemperature
            {
                get { return _CurrentTemperature; }
    
                set
                {
                    if (value != CurrentTemperature)
                    {
                        _CurrentTemperature = value;
                        Console.WriteLine($"Temperature set to {value}");
                        OnTemperatureChange?.Invoke(value);
                    }
                }
            }
    
            private float _CurrentTemperature;
        }
    
        class Cooler
        {
            public Cooler(float temperature)
            {
                Temperature = temperature;
            }
    
            public float Temperature { get; set; }
    
            public void OnTemperatureChanged(float value)
            {
                if (value > Temperature)
                {
                    System.Console.WriteLine("Cooler: On");
                }
                else
                {
                    System.Console.WriteLine("Cooler: Off");
                }
            }
        }
    
        static class Program
        {
            static void Main(string[] args)
            {
                Thermostat thermostat = new Thermostat();
                Cooler cooler = new Cooler(80);
    
                thermostat.OnTemperatureChange += cooler.OnTemperatureChanged;
                Console.Write("Enter new temperature: ");
                string temperature = Console.ReadLine();
                thermostat.CurrentTemperature = int.Parse(temperature);
    
                Console.Read();  //Pause and reflect a moment...
            }
        }
    }
    

    Echo on
  • Options
    urahonkyurahonky Resident FF7R hater Registered User regular
    edited March 2017
    Okay what the fuck is going on with my Django model? I have a field:
    return_slide = models.BooleanField(default=False)
    

    Then when I try to create a slide without that value I get:
    null value in column "return_slide" violates not-null constraint

    But I have a field RIGHT ABOVE IT:
    recut = models.BooleanField(default=False)
    

    And that works just fine.

    edit: I restarted my localhost and it works now. Must be an issue of cache or something.

    urahonky on
  • Options
    CampyCampy Registered User regular
    Thanks for the update Echo, I see what you mean now. Interestingly the book initially taught this method, but with a change of
    public event Action<float> OnTemperatureChange;
    
    to
    public Action<float> OnTemperatureChange;
    
    Strangely (at least I think), this still works fine. Action being quite happy to be used even as a multicast delegate with as many listeners as you want.

    The book speaks of a few disadvantages, but most are only relevant to the latter declaration. Those being allowing the = operator when adding listeners (thus resetting the list and getting rid of any listeners you've already added, ouch!) and allowing the direct invocation of the event function (you could call thermostat.OnTemperatureChange(666) directly for example).

    I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.

    Take all of this with a grain of salt, I'm literally talking about what I've learned over the last 24 hours >_<

  • Options
    EchoEcho ski-bap ba-dapModerator mod
    Campy wrote: »
    I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.

    You can also pass along the object itself in the Invoke call, like I do in the Car class in my example.

  • Options
    bowenbowen How you doin'? Registered User regular
    Can you use dynamic objects as parameters even?

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • Options
    bowenbowen How you doin'? Registered User regular
    dynamic myObj = new { ID: 1, Name: "James" };
    

    something like that

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • Options
    DelzhandDelzhand Hard to miss. Registered User regular
    admanb wrote: »

    I actually did this to myself, sorta. A few months back I created some documentation for how to restart the modem here in the office, because there are a few similar looking devices back there, and I didn't want people accidentally unplugging the modem that the security system uses to dial out, or whatever that other box is.

    Internet went out yesterday. Needed to restart modem. Let me just check the...

    ...

  • Options
    GnomeTankGnomeTank What the what? Portland, OregonRegistered User regular
    Campy wrote: »
    Thanks for the update Echo, I see what you mean now. Interestingly the book initially taught this method, but with a change of
    public event Action<float> OnTemperatureChange;
    
    to
    public Action<float> OnTemperatureChange;
    
    Strangely (at least I think), this still works fine. Action being quite happy to be used even as a multicast delegate with as many listeners as you want.

    The book speaks of a few disadvantages, but most are only relevant to the latter declaration. Those being allowing the = operator when adding listeners (thus resetting the list and getting rid of any listeners you've already added, ouch!) and allowing the direct invocation of the event function (you could call thermostat.OnTemperatureChange(666) directly for example).

    I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.

    Take all of this with a grain of salt, I'm literally talking about what I've learned over the last 24 hours >_<

    What book are you reading that suggests those first two things are equivalent, or that the second one is in any way multicast? The second declaration can only ever have one function assigned to that variable, it's not multicast in the slightest. This book seems to be doing you a major disservice by conflating events and delegates. While events are implemented using delegates, they are not the same thing. For your stated purpose you should absolutely being using an event. Whether you want to follow convention and use TEventArgs with EventHandler<T> is up to you, but you definitely should be using the event keyword.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, NintendoID: Brainling, FF14: Zillius Rosh SFV: Brainling
  • Options
    GnomeTankGnomeTank What the what? Portland, OregonRegistered User regular
    edited March 2017
    So I just broke my work laptop screen, woo. The ThinkPad's they give us at work are totally shite. I had my MacBook sitting on top of it, and the MacBook started to fall. I caught it, but it swung back and made relatively minor contact with the lid of my ThinkPad....caused a complete crack in it and broke the LCD screen. Now I see why: The plastic of the lid is so thin it's comical.

    GnomeTank on
    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, NintendoID: Brainling, FF14: Zillius Rosh SFV: Brainling
  • Options
    admanbadmanb unionize your workplace Seattle, WARegistered User regular
    Campy wrote: »
    You know those moments when you call someone over to ask about why something isn't working and then the moment you start explaining it to them you figure that shit out on your own.

    I just had the same thing but with a really long post here.

    So basically what I'm saying is thanks guys, you solved my problem by just existing!

    Also C# events are not as simple as I would have expected!

    This is one reason why I always wrote emails instead of asking in person (that and I'm awful at remembering stuff I hear vs read) -- half the time I figure out the answer or another approach before I finish the email.

  • Options
    CampyCampy Registered User regular
    GnomeTank wrote: »
    Campy wrote: »
    Thanks for the update Echo, I see what you mean now. Interestingly the book initially taught this method, but with a change of
    public event Action<float> OnTemperatureChange;
    
    to
    public Action<float> OnTemperatureChange;
    
    Strangely (at least I think), this still works fine. Action being quite happy to be used even as a multicast delegate with as many listeners as you want.

    The book speaks of a few disadvantages, but most are only relevant to the latter declaration. Those being allowing the = operator when adding listeners (thus resetting the list and getting rid of any listeners you've already added, ouch!) and allowing the direct invocation of the event function (you could call thermostat.OnTemperatureChange(666) directly for example).

    I believe with the added event keyword that these aren't possible anymore. Thus I think the only advantage to using the full TEventArgs delegate is that the listener now has access to the provider object via the first parameter required by EventHandler. This would come in handy if the listener has been added to more than one provider and thus can then know which one has called it.

    Take all of this with a grain of salt, I'm literally talking about what I've learned over the last 24 hours >_<

    What book are you reading that suggests those first two things are equivalent, or that the second one is in any way multicast? The second declaration can only ever have one function assigned to that variable, it's not multicast in the slightest. This book seems to be doing you a major disservice by conflating events and delegates. While events are implemented using delegates, they are not the same thing. For your stated purpose you should absolutely being using an event. Whether you want to follow convention and use TEventArgs with EventHandler<T> is up to you, but you definitely should be using the event keyword.

    It's Essential C# 6.0 5th edition by Mark Michaelis and Eric Lippert.

    Perhaps I'm misunderstanding the terminology of multicast. I was definitely able to add multiple listeners using OnTemperatureChange without declaring it as an event, is this all that is meant by multicast or is there more involved? I agree it does seem really odd that this works! The code below gives the correct (as far as I can figure) output.

    You can add as many cooler/heaters as you like and it still seems to work. The book even had me messing around with inserting a delegate function via a lambda which threw an exception to show how to handle such things.

    output:
    Enter new temperature: 100
    Temperature set to 100
    Cooler: On
    Heater: Off
    

    I just realised I should probably stop shitting up the thread with massive reams of code, so it's spoilered...
    using System;
    
    namespace ConsoleApplication1
    {
     
      public static class ThermostatTestings
      {
        public static void ThermostatTest()
        {
          Thermostat thermostat = new Thermostat();
          
          Cooler cooler = new Cooler(80);
          Heater heater = new Heater(50);
          
          thermostat.OnTemperatureChange += cooler.OnTemperatureChanged;
          thermostat.OnTemperatureChange += heater.OnTemperatureChanged;
    
          Console.Write("Enter new temperature: ");
          string temperature = Console.ReadLine();
          thermostat.CurrentTemperature = int.Parse(temperature);
        }
      }
    
      public class Thermostat
      {
        public Action<float> OnTemperatureChange;
        
        public float CurrentTemperature
        {
          get { return _CurrentTemperature; }
    
          set
          {
            if (value != CurrentTemperature)
            {
              _CurrentTemperature = value;
              Console.WriteLine($"Temperature set to {value}");
              OnTemperatureChange?.Invoke( value );
            }
          }
        }
    
        private float _CurrentTemperature;
      }
    
      class Cooler
      {
        public Cooler(float temperature)
        {
          Temperature = temperature;
        }
    
        public float Temperature { get; set; }
    
        public void OnTemperatureChanged(float NewTemperature)
        {
          if (NewTemperature > Temperature)
          {
            System.Console.WriteLine("Cooler: On");
          }
          else
          {
            System.Console.WriteLine("Cooler: Off");
          }
        }
      }
    
      class Heater
      {
        public Heater(float temperature)
        {
          Temperature = temperature;
        }
    
        public float Temperature { get; set; }
    
        public void OnTemperatureChanged(float NewTemperature)
        {
          if (NewTemperature < Temperature)
          {
            System.Console.WriteLine("Heater: On");
          }
          else
          {
            System.Console.WriteLine("Heater: Off");
          }
        }
      }
    }
    

  • Options
    GnomeTankGnomeTank What the what? Portland, OregonRegistered User regular
    And then someone comes along and does thermostat.OnTemperatureChange = Handler, or worse yet thermostat.OnTemperatureChange = null, and you lose all the others. Plus this is relying on an implementation detail of CLR delegates, which is that they can have multiple handlers attached to them in the empty state, and implementation detail you are not supposed to rely on and could go away at any time. It's bad C#, and the fact that a book is teaching it to you as "a good way to do things" is frustrating.

    Sagroth wrote: »
    Oh c'mon FyreWulff, no one's gonna pay to visit Uranus.
    Steam: Brainling, XBL / PSN: GnomeTank, NintendoID: Brainling, FF14: Zillius Rosh SFV: Brainling
  • Options
    OghulkOghulk Tinychat Janitor TinychatRegistered User regular
    Would a good way to work with classes and to do some more complex algorithm type stuff be to make classes based on everyday objects/activities I use/do?

  • Options
    DehumanizedDehumanized Registered User regular
    edited March 2017
    Oghulk wrote: »
    Would a good way to work with classes and to do some more complex algorithm type stuff be to make classes based on everyday objects/activities I use/do?

    It can be instructive but not necessarily lead to the best designs. Here's an example that illustrates it pretty well. The author proposes a design problem (structure a coffee machine design that can do some stuff) then shows how a design that reflects the physical object doesn't quite capture the right abstractions to allow for a clean design.

    http://heim.ifi.uio.no/~mmo/generic/papers/coffee/Coffee-1.html

    It's remarkably similar to a section in Agile Patterns Principles and Practices in C# which is a book I'd highly recommend if you work in C#.


    edit: whoops, forgot to include part 2 of the paper:

    http://heim.ifi.uio.no/~mmo/generic/papers/coffee/Coffee-2.html

    Dehumanized on
  • Options
    CampyCampy Registered User regular
    GnomeTank wrote: »
    And then someone comes along and does thermostat.OnTemperatureChange = Handler, or worse yet thermostat.OnTemperatureChange = null, and you lose all the others. Plus this is relying on an implementation detail of CLR delegates, which is that they can have multiple handlers attached to them in the empty state, and implementation detail you are not supposed to rely on and could go away at any time. It's bad C#, and the fact that a book is teaching it to you as "a good way to do things" is frustrating.

    Interestingly enough the book even states these problems before going onto teaching the proper events methodology. Quite why it bothered I'm not sure... I will most certainly be using events for all such things!

    Thanks for all the feedback chaps, being back in OO feels great!

  • Options
    jaziekjaziek Bad at everything And mad about it.Registered User regular
    We're starting a new project at work to write a CRM which integrates with all our other products.

    Why we're doing this and not just making integration modules for the big name CRMs that are way better than anything we could do I don't know, but whatever.

    Having said that, it's a cool opportunity to play with some new frameworks and such. We're going with Vue for the front end, and while I'm not really one for JS if I can help it, vue looks surprisingly palatable.

    Steam ||| SC2 - Jaziek.377 on EU & NA. ||| Twitch Stream
  • Options
    vimmervimmer Registered User regular
    edited March 2017
    Hey guys I have a design question,

    I'm working on a roles based permission system. In this application there are users and users have many different types of private resources that they can CRUD.

    Some users with a certain role will have permission to view other users resources. The problem is I need to provide fine-grained control over which user's resources they will be allowed to view and which ones they will be blocked from viewing.

    Is there a pattern for implementing such a system without having to explicitly specify all the user IDs per resource that role is allowed to access? There could be hundreds of users and dozens of roles...

    In some cases a role could be restricted to seeing only a handful of users, and in others it might be able to see every user except for a few.

    I was thinking about creating per resource one boolean value that specifies if that role can see everyone by default, and then creating a list of user IDs to include or exclude per resource.

    Maybe this concept has a name?



    vimmer on
  • Options
    schussschuss Registered User regular
    vimmer wrote: »
    Hey guys I have a design question,

    I'm working on a roles based permission system. In this application there are users and users have many different types of private resources that they can CRUD.

    Some users with a certain role will have permission to view other users resources. The problem is I need to provide fine-grained control over which user's resources they will be allowed to view and which ones they will be blocked from viewing.

    Is there a pattern for implementing such a system without having to explicitly specify all the user IDs per resource that role is allowed to access? There could be hundreds of users and dozens of roles...

    In some cases a role could be restricted to seeing only a handful of users, and in others it might be able to see every user except for a few.

    I was thinking about creating per resource one boolean value that specifies if that role can see everyone by default, and then creating a list of user IDs to include or exclude per resource.

    Maybe this concept has a name?



    You're building a security system? There's a ton of potential solutions out there for this. I know for our system we have a reference table of available resources, and they get some or all of them as rights in a copied version that the program checks on login/render every time to determine what they have access to.
    I can talk more detail if you can give some more concrete examples.
    Key concepts to think about: Are new resources going to be centrally added or just pop in all the time created by users? What's the timing needed between change to resource rights and when it needs to happen (is it immediate or within a few minutes?)? What high-level role frameworks do you expect to have (IE Security Admin, Security Worker, User, Super User etc.)? What's the rate of change?
    Generally I think you want to store resource rights with a user rather than vice versa, as then you have more options around master user control instead of master resource control (IE - someone gets fired it's much easier to just shut down a centralized master user record that's the reference for all other rights)
    Is this a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type thing?

  • Options
    a5ehrena5ehren AtlantaRegistered User regular
    PROTIP:

    WRITING FUCKING
    /* An error message would probably be helpful here*/
    
    TAKES JUST AS LONG AS JUST WRITING GOD-DAMN
    syslog(log_err, "%s:%s error whatever\n", __FILE__, __LINE__);
    

    AND ONE OF THESE PROVIDES USEFUL INFORMATION WHEN YOUR FUCKING INSANE "MANUALLY EDIT /ETC/PASSWD/ AND DON'T USE THE SYSTEM TOOLS" CODE BREAKS!

  • Options
    RendRend Registered User regular
    a5ehren wrote: »
    PROTIP:

    WRITING FUCKING
    /* An error message would probably be helpful here*/
    
    TAKES JUST AS LONG AS JUST WRITING GOD-DAMN
    syslog(log_err, "%s:%s error whatever\n", __FILE__, __LINE__);
    

    AND ONE OF THESE PROVIDES USEFUL INFORMATION WHEN YOUR FUCKING INSANE "MANUALLY EDIT /ETC/PASSWD/ AND DON'T USE THE SYSTEM TOOLS" CODE BREAKS!

    I feel like a specific event drove you to provide us with this quick protip.

  • Options
    bowenbowen How you doin'? Registered User regular
    is syslog valid iso C++ though?

    I thought it was part of the GNU compiler suite or whatever?

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • Options
    a5ehrena5ehren AtlantaRegistered User regular
    edited March 2017
    bowen wrote: »
    is syslog valid iso C++ though?

    I thought it was part of the GNU compiler suite or whatever?

    This code has always been on GNU/C and is not switching off of it in the foreseeable future.

    a5ehren on
  • Options
    DehumanizedDehumanized Registered User regular
    every comment is someone making an excuse for their insufficiently expressive code

  • Options
    ecco the dolphinecco the dolphin Registered User regular
    edited March 2017
    every comment is someone making an excuse for their insufficiently expressive code

    // TODO: Reply

    // Rev 2: think about agreeing?

    // Rev 3: fix typo how did this even compile?

    ecco the dolphin on
    Penny Arcade Developers at PADev.net.
  • Options
    RendRend Registered User regular
    every comment is someone making an excuse for their insufficiently expressive code
    //Note: this todo is no longer necessary for current api version
    //TODO: Reply

  • Options
    bowenbowen How you doin'? Registered User regular
    a5ehren wrote: »
    bowen wrote: »
    is syslog valid iso C++ though?

    I thought it was part of the GNU compiler suite or whatever?

    This code has always been on GNU/C and is not switching off of it in the foreseeable future.

    Welp, deffo no excuses then!

    not a doctor, not a lawyer, examples I use may not be fully researched so don't take out of context plz, don't @ me
  • Options
    a5ehrena5ehren AtlantaRegistered User regular
    edited March 2017
    a5ehren wrote: »
    bowen wrote: »
    is syslog valid iso C++ though?

    I thought it was part of the GNU compiler suite or whatever?

    This code has always been on GNU/C and is not switching off of it in the foreseeable future.

    To follow up: syslog() is part of Standard UNIX(tm), not just GNU Libc. And we're sure as hell not moving off of a UNIX-like anytime soon.

    a5ehren on
  • Options
    vimmervimmer Registered User regular
    schuss wrote: »
    vimmer wrote: »
    Hey guys I have a design question,

    I'm working on a roles based permission system. In this application there are users and users have many different types of private resources that they can CRUD.

    Some users with a certain role will have permission to view other users resources. The problem is I need to provide fine-grained control over which user's resources they will be allowed to view and which ones they will be blocked from viewing.

    Is there a pattern for implementing such a system without having to explicitly specify all the user IDs per resource that role is allowed to access? There could be hundreds of users and dozens of roles...

    In some cases a role could be restricted to seeing only a handful of users, and in others it might be able to see every user except for a few.

    I was thinking about creating per resource one boolean value that specifies if that role can see everyone by default, and then creating a list of user IDs to include or exclude per resource.

    Maybe this concept has a name?



    You're building a security system? There's a ton of potential solutions out there for this. I know for our system we have a reference table of available resources, and they get some or all of them as rights in a copied version that the program checks on login/render every time to determine what they have access to.
    I can talk more detail if you can give some more concrete examples.
    Key concepts to think about: Are new resources going to be centrally added or just pop in all the time created by users? What's the timing needed between change to resource rights and when it needs to happen (is it immediate or within a few minutes?)? What high-level role frameworks do you expect to have (IE Security Admin, Security Worker, User, Super User etc.)? What's the rate of change?
    Generally I think you want to store resource rights with a user rather than vice versa, as then you have more options around master user control instead of master resource control (IE - someone gets fired it's much easier to just shut down a centralized master user record that's the reference for all other rights)
    Is this a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type thing?


    To answer:

    -New resources are popping in all the time created by users.
    -Changes to rights happen immediately
    -Most of the roles are not really IT type of roles, rather they are more like organizational and company type roles.
    -Rate of change, once a role is defined it usually doesn't need to change.

    I could store resource rights with a user, but then it makes it a cumbersome experience when you have for example a "Service Department" role with 10 users and they all need the same level of access to certain resources of a subset of users.

    If someone is fired there is a user record in the database that could simply have a disabled flag set that would prevent them from logging in or using any API routes.

    It is a "people own stuff but some people are helpers that need to see everything except in sensitive cases then only a few can" type of thing.


    I already have a roles system implemented that allows for fine-grain control of what users can and can't do based on activities. Resource access though is still a harder problem to design for because of the variable amount of users over time.

This discussion has been closed.