NewFiveFour | Blog | Portfolio


CSS: Grid

So CSS grid lets align your divs in grids. It's more visual and slightly less confusing than flexbox but needs more css -- harder to quickly hack.
 
Our grid will have a top spanning header, an image under the header to the left and a text area to the right of the image.

    <div id="grid">
        <div class="head">heading</div>
        <div class="img">img</div>
        <div class="text">text</div>
    </div>

Let's give it each element a background colour and a border:

<style>
    div {
        border: solid black 1px;
    }
    .head {
        font-size: 40px;
        background-color: lightblue;
    }
    .text {
        background-color: lightgrey;
    }

    .img {
        background-color: lightgreen;
    }
</style>  

It isn't a grid yet. Let's make one with a 200px height:

    #grid {
        height: 200px;
        display: grid;
        grid-template: 
        'head head head' 25%
        'img text text' auto
        'img text text' auto
        / 30% auto auto;
    }

We name of grid pieces in quotation marks on three separate lines.
After each line we specify the height: 25% and auto and auto, in our case.
 
After the three lines, we specify the row widths after a slash: 30% and auto and auto.
 
So that's done: https://repl.it/repls/UncommonConcreteInitializationfile
 
But we want to centre our header. We could use some css grid properties. But that would centre our head div, including the background colour. So let's just use css flexbox instead:
 

    .head {
        font-size: 40px;
        background-color: lightblue;
        display: flex;
        justify-content: center;
        align-items: center;
    }


css css-grid


NFtables basics

NFtables replaces the iptable firewall tools in Linux. It should make things nicer. But let's step back and talk about how firewalls are organised.
 
Background
 
Firewalls are made up of rules. An example is "allow incoming connections on port 22". Rules are organised into chains. There are two main chains, input and output. Rules on the input chain relate to incoming connections. Rules on the output chain relate to outgoing connections. A table is a collection of chains.
 
We can make our own table and chains. Our chains will hook onto the default input or output chain. Linux will see an incoming connection. It will consult the default input chain. That input chain will then consult our chain.
 
Allowing ports
 
So let's look at the format of nft commands: nft THE_COMMAND inet THE_TABLE THE_CHAIN THE_CHAIN_COMMAND.
 
After nft you type the command name, then then you specify the table name (but with inet before because the table will be a ipv4/6 table), then the chain name, then the chain command. In short: the command, inet plus the table name, the chain name and the chain command.
 
Let's make our table and chain, the chain that will hook onto the default input chain and filter things on that.

nft add table inet mytable
nft add chain inet mytable myinputchain { type filter hook input priority 0 \; }

Let's add rules to allow SSH on port 22 and HTTPS on 442 and drop everything else. The chain command format is: type tcp, then dport and the number and finally the accept/drop.

nft add rule inet mytable myinputchain tcp dport {443, 22} accept
nft add rule inet mytable myinputchain drop

Inserting rules and allowing established connections
 
But we forgot to add a rule before drop. We want to add one before that but first we need to know the nft position of the rule above drop. We can do that with nft list table inet mytable -a -nn:

table inet mytable {
	chain myinputchain {
		type filter hook input priority 0; policy accept;
		tcp dport 22 accept # handle 2
		tcp dport 443 accept # handle 3
		drop # handle 4
	}
}

So we know it's handle 3 now. We will type position 3 before our chain command.
 
When we establish a connection to the outside world, the outside world will want to talk to us, but our firewall will reject it because it won't send us things on port 443 or 22. We need to track the connections (ct) we make, and look at the state of the connection, and if we've established it, then allow it.

nft add rule inet mytable myinputchain position 3 ct state established accept

Saving and restoring rules
 
Let's save our list with nft list table inet mytable -a -nn > fw.ruleset, clear our nft table with nft delete table inet mytable, see nothing is there by looking at nft list tables, then reload it with nft -f fw.ruleset and then check all the rules are there.
 
Allowing pings and rate limiting
 
We should allow pings. Our table is a ipv4/ipv6 table so we need to specify that we're interested in the icmp protocol, then the type of icmp packet that interests, then we set a rate limit to stop ping flood, then accept. After this we drop any icmp packet else the established packet rule will accept the ping floods.

nft add rule inet mytable myinputchain position <..before drop..> ip protocol icmp icmp type echo-request limit rate 1/second accept
nft add rule inet mytable myinputchain position <after the above> ip protocol icmp drop

Allowing the loop back device
 
Local programs communicate with the computer using the loopback device. Let's allow that. We use the meta command to look at the networking packets, and look at the interface name with iif. After this we should be able to ping localhost.

nft insert rule inet mytable myinputchain position 2 meta iif lo accept

In conclusion
 
If we put all this together, we get:

nft add table inet mytable
nft add chain inet mytable myinputchain { type filter hook input priority 0 \; }
nft add rule inet mytable myinputchain meta iif lo accept
nft add rule inet mytable myinputchain tcp dport {443, 22, 3000, 3002} accept
nft add rule inet mytable myinputchain ip protocol icmp icmp type echo-request limit rate 1/second accept
nft add rule inet mytable myinputchain ip protocol icmp drop
nft add rule inet mytable myinputchain ct state established accept
nft add rule inet mytable myinputchain drop

unix nftables


Java and Android: Dagger 2 introduction (including Component.Builder)

Let's work through an example of Dagger 2. I'm doing it this in an Android project but for simplicity we'll be treating the project like a normal Java project for the most part: there will be no Activity or Fragment specific code. First this this in our gradle.build file:

annotationProcessor 'com.google.dagger:dagger-compiler:2.20'
implementation 'com.google.dagger:dagger:2.20'

We have a Drink class. This has a taste method. The taste method prints out the ingredients in the drink. The Ingredients are held as a instance method in the class. Normally we would pass the ingredients in a constructor parameters. But instead we use the @Inject annotation on a member field. Later Dagger will inject an implmentation of Ingredients here. (We must also annotate Drink with @Inject to keep Dagger happy when creating Drink.)

public class Drink {

    public static interface Ingredients {
        List<String> getAll();
    }

    @Inject
    public Drink() {}

    @Inject
    Ingrediants ingredients;

    public void taste() {
        System.out.println("Our drink contains: " + ingredients.getAll());
    }
}

We now use a Dagger Module to define our dependencies. In our case, our dependency is Ingredient. We make a plain class and annotate it with @Module. In that class we have a method that's annotated with @Provides and that method returns our Ingredients. The name of method could actually be anything - the only thing that matters is the return type.
 
(Note: we are explicity detailing our ingredients implementation in the module. Later we'll learn how to do this in a more dynamic way)
 
We must have a Component class. This let's us begin our dependency injection. You need to create an interface. And this is annotated with @Component. And the parameters to that annotation is our Module that we created above. Inside our component we have an inject method. The paramter is the type of class which we will use our dependency injection.

@Component(modules = DrinkModule.class)
interface BarComponent {

  void inject(MainActivity activity);

  @Module
  public class DrinkModule {

    @Provides public Ingredients providesIngredients() {
      return new Ingrediants() {
          @Override
          public List<String> getAll() {
              return Arrays.asList("GIN", "Orange Juice", "Coke");
          }
      };
    }
  }
}

We've made our module with the dependencies that lives inside our component. So we can now use the component. Dagger automatically creates a class DaggerBarComponent that's based on our BarComponent class. We then call the builder() method that returns a builer. We're not currently doing anything special so we call 'build()'. And we've built our component, we call the inject method -- passing in our current class.
 
At the point, any instance methods in the current class that have the @Inject annotation will be initiated by Dagger. And importantly its dependency's will be resolved. For instance, we have @Inject Drink drink and Dagger will create Drink, look at all the instance methods, for example, @Inject Ingredients ingredient, and resolve those using Dagger's component and module.

@Inject Drink drink;
...
DaggerBarComponent
  .builder()
  .inject(this);
...
drink.taste()

We previously hard-coded our Ingredients "GIN", "Orange Juice" and "Coke" in our module. We can instead pass those into our component. We do this using a dagger factory. We do this using an interface annnotated with @Component.Builder. We have a method that returns that interface. It also has an argument of, in our case, List<String> ingredeients. We must have an extra method called build that returns the component. The second thing we do is alter the providesIngredients method in our module. This method now takes in the List<String> ingredients and uses it.

@Component(modules = { BarComponent.DrinkModule.class })
interface BarComponent {

    @Component.Builder
    interface Builder {
        @BindsInstance Builder ingredients(List<String> ingredients);
        BarComponent build();
    }

    void inject(MainActivity activity);

    @Module
    class DrinkModule {

        @Provides
        public Drink.Ingredients providesIngredients(final List<String> ingredients) {
            return new Drink.Ingredients() {
                @Override
                public List<String> getAll() {
                    return ingredients;
                }
            };
        }

    }
}

Now when we build our module we can pass in the List<String> ingredients:

DaggerBarComponent
  .builder()
  .ingredients(Arrays.asList("Vodka", "Rum", "Coke"))
  .build()
  .inject(this);

You can also then use Android's build types to swap in or out the depedencies depending on the build type:

List<String> ingredients = null;
if(BuildConfig.BUILD_TYPE.equals("teeTotal")) {
    ingredients = Arrays.asList("Orange", "Soda", "Pineapple");
} else if(BuildConfig.BUILD_TYPE.equals("alcoholic")) {
    ingredients = Arrays.asList("Vodka", "Rum", "Coke");
}

DaggerBarComponent
  .builder()
  .ingredients(ingredients)
  .build()
  .inject(this);

drink.taste();

By specifying two build types in your app/build.gradle file:

...
android {
  ...
    buildTypes {
      ..
      teeTotal {
        initWith debug
      }
      alcoholic {
        initWith debug
      }
    }
  ...
}
...

And then using adb to either ./gradlew installAlcoholic or ./gradlew installTeeTotal. And then you can see the different output in logcat.

java dagger android


Android: Live Data

Live data is a way for you to observe changes to data. Let's use it in a ViewModel:

import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    public MutableLiveData<String> text = new MutableLiveData<>();

    public LiveData<String> getText() {
        return text;
    }

    public void setText(String text) {
        this.text.setValue(text);
    }
}

Instead of having a plain String we have a MutableLiveData object. And when we want to update data we use setValue.
 

getText() returns a LiveData object. Let's see how we use that in our activity or fragment:

MyViewModel vm = ViewModelProviders.of(this).get(MyViewModel.class);

vm.getText().observe(this, new Observer<String>() {
    @Override
    public void onChanged(@Nullable String s) {
        ((TextView)findViewById(R.id.aTextView)).setText(s);
    }
});

We observe it. So when it changes we update our view.

android android-lifecycle


Java: Using autovalue

Google's AutoValue helps us create a Java builder, amongst other things.
 
Let's first include it in our build.gralde:

implementation "com.google.auto.value:auto-value-annotations:1.6.1"
annotationProcessor 'com.google.auto.value:auto-value:1.6.1'

Then use the @AutoValue annotation on our abstract POJO with abstract methods.
 
And @AutoValue.Builder on a static abstract inner class that has abstract setters and a build method.

@AutoValue
public abstract class SomePOJO {
    public abstract String name();
    public abstract int age();

    @AutoValue.Builder
    public abstract static class Builder {
        public abstract SomePOJO build();
        public abstract Builder name(String name);
        public abstract Builder age(int age);
    }

    public static SomePOJO build() {
        return new AutoValue_SomePOJO.Builder()
                .age(100)
                .name("Dave")
                .build();
    }
}

We can then use the generated AutoValue_SomePOJO object to use the Builder class and methods.
 
If we pass null into any of the setters, Auto throws an IllegalStateException and tells us what we're missing.

java java-autovalue


Page 1 of 96
next

Portfolio