{"id":287,"date":"2020-08-10T07:21:00","date_gmt":"2020-08-10T04:21:00","guid":{"rendered":"https:\/\/blog.gunlerveisler.gen.tr\/?p=287"},"modified":"2020-09-21T04:11:28","modified_gmt":"2020-09-21T01:11:28","slug":"about-my-abortive-design","status":"publish","type":"post","link":"https:\/\/aliyargunes.com.tr\/blog\/about-my-abortive-design\/","title":{"rendered":"About My Abortive Design"},"content":{"rendered":"\n<p>Here is an idea for managing the user permissions at my web app. In this design users have different privileges to perform basic crud operations on different app domains (Customer Management Domain, Stock Management Domain etc.). In this way, some specific areas or functions hiding\/showing to the user also, and an admin user can grant these permissions. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">User Entity:<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\n@Table(name = &quot;Users&quot;)\npublic class Users {\n\t\n\t@Id\n\t@GeneratedValue\n\t@Column(name = &quot;id&quot;)\n\tprivate Long id;\n\t\n\t@Column(name=&quot;firstname&quot;)\n\tprivate String firstname;\n\t\n\t@Column(name=&quot;lastname&quot;)\n\tprivate String lastname;\n\t\n\t@OneToMany(cascade = CascadeType.ALL)\n    @JoinTable(name = &quot;name_permission_mapping&quot;, \n      joinColumns = {@JoinColumn(name = &quot;user_id&quot;, referencedColumnName = &quot;id&quot;)},\n      inverseJoinColumns = {@JoinColumn(name = &quot;permission_id&quot;, referencedColumnName = &quot;id&quot;)})\n    @MapKey(name = &quot;permission_name&quot;)\n\tprivate Map&lt;String, Permission&gt; _roles = new HashMap&lt;&gt;();\n\t\n\tpublic Users() {\n\t\tsuper();\n\t}\n\t\n\tpublic Users(String firstname, String lastname, Map&lt;String, Permission&gt; roles) {\n\t\tsuper();\n\t\tthis.firstname = firstname;\n\t\tthis.lastname = lastname;\n\t\tthis._roles = roles;\n\t}\n\n\t\/\/ getters + setters + toString\n\t\n}\n\n<\/pre><\/div>\n\n\n<!--more-->\n\n\n\n<h3 class=\"wp-block-heading\">User Builder:<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class UsersBuilder {\n\t\n\tprivate String firstname;\n\tprivate String lastname;\n\tMap&lt;String, Permission&gt; Permissions = new HashMap&lt;&gt;();\n\t\n\tpublic UsersBuilder setFirstname(String firstname) {\n\t\tthis.firstname = firstname;\n\t\treturn this;\n\t}\n\t\n\tpublic UsersBuilder setLastname(String lastname) {\n\t\tthis.lastname = lastname;\n\t\treturn this;\n\t}\n\t\n\tpublic UsersBuilder setPermissions(Map&lt;String, Permission&gt; p) {\n\t\tthis.Permissions = p;\n\t\treturn this;\n\t}\n\t\n\tpublic Users build() {\n\t\treturn new Users(firstname, lastname, Permissions);\n\t}\n\t\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">User Service:<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class UserPermissionService {\n\t\n\t\n\tpublic boolean createPermissionProvider(Permission p, Users u) {\n\t\treturn u.get_roles().get(p.getClass().getSimpleName()) != null\n\t\t\t\t? checkUserWritePermission(p, u)\n\t\t\t\t: false;\n\t}\n\t\n\tpublic boolean readPermissionProvider(Permission p, Users u) {\n\t\treturn u.get_roles().get(p.getClass().getSimpleName()) != null\n\t\t\t\t? checkUserReadPermission(p, u)\n\t\t\t\t: false;\n\t}\n\t\n\tpublic boolean updatePermissionProvider(Permission p, Users u) {\n\t\treturn u.get_roles().get(p.getClass().getSimpleName()) != null\n\t\t\t\t? checkUserUpdatePermission(p, u)\n\t\t\t\t: false;\n\t}\n\t\n\tpublic boolean deletePermissionProvider(Permission p, Users u) {\n\t\treturn u.get_roles().get(p.getClass().getSimpleName()) != null\n\t\t\t\t? checkUserDeletePermission(p, u)\n\t\t\t\t: false;\n\t}\n\t\n\tpublic boolean checkUserWritePermission(Permission p, Users user) {\n\t\treturn user.get_roles().get(p.getClass().getSimpleName()).is_create();\n\t}\n\t\n\tpublic boolean checkUserReadPermission(Permission p, Users user) {\n\t\treturn user.get_roles().get(p.getClass().getSimpleName()).is_read();\n\t}\n\t\n\tpublic boolean checkUserUpdatePermission(Permission p, Users user) {\n\t\treturn user.get_roles().get(p.getClass().getSimpleName()).is_update();\n\t}\n\t\n\tpublic boolean checkUserDeletePermission(Permission p, Users user) {\n\t\treturn user.get_roles().get(p.getClass().getSimpleName()).is_delete();\n\t}\n\t\n\t\/\/ ...\n\t\n\tpublic boolean grantPermission(Permission p, Users user) {\n\t\treturn user.get_roles().put(p.getClass().getSimpleName(), p) != null\n\t\t\t\t? true : false;\n\t}\n\t\n\tpublic boolean removePermission(Permission p, Users user) {\n\t\treturn user.get_roles().remove(p.getClass().getSimpleName(), p);\n\t}\n\t\n\tpublic Permission findPermission(Permission p, Users user) {\n\t\treturn user.get_roles().get(p.getClass().getSimpleName());\n\t}\t\t\n}\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Permission Base Class:<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic class Permission {\n\t\n\t@Id\n\t@GeneratedValue\n\tprivate Long id;\n\t\n\t@Column(name=&quot;permission_name&quot;)\n\tprivate String permission_name;\n\t\n\t@Column(name = &quot;_create&quot;)\n\tprivate boolean _create;\n\t\n\t@Column(name = &quot;_read&quot;)\n\tprivate boolean _read;\n\t\n\t@Column(name = &quot;_update&quot;)\n\tprivate boolean _update;\n\t\n\t@Column(name = &quot;_delete&quot;)\n\tprivate boolean _delete;\n\t\n\t\/\/ getters + setters + toString\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Permission Subclass 1: <\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\npublic class CustomerDomainPermission extends Permission {\n\tpublic CustomerDomainPermission() {\n\t\tsuper();\n\t}\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Permission Subclass 2:<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\npublic class ProductDomainPermission extends Permission {\n\tpublic ProductDomainPermission() {\n\t\tsuper();\n\t}\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Test Class: <\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class PermissionsTest {\n\t\npublic static void main(String&#x5B;] args) {\n\t\n\t\tPermission cd = new CustomerDomainPermission();\n\t\tcd.set_read(true);\n\t\tcd.set_create(true);\n\t\tcd.set_delete(true);\n\t\tcd.set_update(true);\n\t\tcd.setPermission_name(&quot;customer_domain&quot;);\n\t\t\n\t\tPermission pd = new ProductDomainPermission();\n\t\tpd.set_read(true);\n\t\tpd.set_create(true);\n\t\tpd.set_delete(true);\n\t\tpd.set_update(true);\n\t\tpd.setPermission_name(&quot;product_domain&quot;);\n\t\t\n\t\tUsers user = new UsersBuilder()\n\t\t\t\t.setFirstname(&quot;Walter&quot;)\n\t\t\t\t.setLastname(&quot;White&quot;)\n\t\t\t\t.build();\n\t\t\t\t\n\t\tUserPermissionService us = new UserPermissionService();\n\t\tus.grantPermission(pd, user);\n\t\tus.grantPermission(cd, user);\n\t\t\n\t\tnew UserDao().addUser(user);\n                System.out.println(user);\n\t}\n}\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Output:<\/h3>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nUsers &#x5B;id=1, firstname=Walter, lastname=White, _roles={ProductDomainPermission=Permission &#x5B;id=2, permission_name=product_domain, _create=true, _read=true, _update=true, _delete=true], CustomerDomainPermission=Permission &#x5B;id=3, permission_name=customer_domain, _create=true, _read=true, _update=true, _delete=true]}]\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Database Tables:<\/h3>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_01.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"338\" height=\"339\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/table_01.jpg\" alt=\"\" class=\"wp-image-293\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_01.jpg 338w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_01-300x300.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_01-150x150.jpg 150w\" sizes=\"(max-width: 338px) 100vw, 338px\" \/><\/a><figcaption>Hibernate Equivalent Tables<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_02.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"414\" height=\"271\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/table_02.jpg\" alt=\"\" class=\"wp-image-295\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_02.jpg 414w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_02-300x196.jpg 300w\" sizes=\"(max-width: 414px) 100vw, 414px\" \/><\/a><figcaption>User Base Class Table<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_033.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"453\" height=\"340\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/table_033.jpg\" alt=\"\" class=\"wp-image-315\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_033.jpg 453w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_033-300x225.jpg 300w\" sizes=\"(max-width: 453px) 100vw, 453px\" \/><\/a><figcaption>Permission Base Class (Inherited) as Empty Table<\/figcaption><\/figure><\/div>\n\n\n\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_04.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"950\" height=\"417\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/table_04.jpg\" alt=\"Customer Domain Subclass Table\" class=\"wp-image-297\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_04.jpg 950w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_04-300x132.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_04-768x337.jpg 768w\" sizes=\"(max-width: 950px) 100vw, 950px\" \/><\/a><figcaption>Customer Domain Subclass Table<\/figcaption><\/figure><\/div>\n\n\n\n<p><\/p>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-image is-style-default\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_05.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"949\" height=\"416\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/table_05.jpg\" alt=\"Product Domain Subclass Table\" class=\"wp-image-298\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_05.jpg 949w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_05-300x132.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_05-768x337.jpg 768w\" sizes=\"(max-width: 949px) 100vw, 949px\" \/><\/a><figcaption>Product Domain Subclass Table<\/figcaption><\/figure><\/div>\n<\/div><\/div>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_06.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/table_06.jpg\" alt=\"\" class=\"wp-image-299\" width=\"454\" height=\"346\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_06.jpg 454w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/table_06-300x229.jpg 300w\" sizes=\"(max-width: 454px) 100vw, 454px\" \/><\/a><figcaption>Intermediary Table which created by Hibernate automatically for User and inherited Permission association<\/figcaption><\/figure><\/div>\n\n\n\n<p><strong>Pros of this design:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>When new requirements of application domains come (for example &#8220;Stock Domain&#8221; or &#8220;Invoice Management Domain&#8221; etc. ) only need to do is just create another subclass of Permission. (also obeyed <em><strong>Open-Closed Principle<\/strong><\/em>, SOLID) This can require significantly less programming effort because the base class contains many methods providing default behavior.<\/li><li>The association between Users and Permission classes simply stored at &#8220;permissions&#8221; map collection attribute in the Users base class. <\/li><li>It needs only one base service class and 8 methods for all of its subclasses. (<em><strong>Composition<\/strong><\/em>)<\/li><\/ul>\n\n\n\n<p class=\"has-text-align-left\">But I hesitate to use this, because the database is not in a good shape, there are some repetitive columns at the &#8220;<code>ProductDomainPermission<\/code>&#8221; and &#8220;<code>CustomerDomainPermission<\/code>&#8221; tables, such as &#8220;<code>permission_name<\/code>&#8220;, this is an illegal situation at the context of <strong><em>First Normal Form<\/em><\/strong> database property. This may cause performance issues once project starts to grow. Also,<em> <strong>Map<\/strong><\/em> collection attribute seems like misused and &#8220;<code>Users<\/code>&#8221; entity is not loosely coupled to the permission code block. Consequently, It looks not very good to me, so I give up the idea.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>But, Instead of this I thought up another solution:<\/strong><\/h3>\n\n\n\n<p>I decided to use a &#8220;<code>DomainPermissions<\/code>&#8221; type instead of a Map Collection attribute inside the &#8220;<code>Users<\/code>&#8221; class, it consists of 4 primitive boolean attribute which represent crud operation permissions, so that <code>\"Users<\/code>&#8221; decouples from &#8220;<code>Permission<\/code>&#8220;. Also, create OneToOne associations and constraints among the Permission Persistent Block and the Users explicitly, in this way I had more control over Hibernate to shaping database.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/umlDiagram.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"530\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/umlDiagram-1024x530.jpg\" alt=\"\" class=\"wp-image-360\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/umlDiagram-1024x530.jpg 1024w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/umlDiagram-300x155.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/umlDiagram-768x397.jpg 768w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/umlDiagram.jpg 1082w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/a><figcaption>UML diagram of new design<\/figcaption><\/figure>\n\n\n\n<p><strong>Users Class<\/strong>:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\nEntity\n@Table(name = &quot;Users&quot;)\npublic class Users {\n\t\n\t@Id\n\t@GeneratedValue\n\t@Column(name = &quot;user_id&quot;)\n\tLong user_id;\n\t\n\t@Column(name=&quot;firstname&quot;)\n\tprivate String firstname;\n\t\n\t@Column(name=&quot;lastname&quot;)\n\tprivate String lastname;\n\t\n\t@OneToOne(cascade = CascadeType.ALL, \n\t\t\torphanRemoval = true)\n\t@JoinColumn(name = &quot;_domainPermission_id&quot;, referencedColumnName = &quot;domainPermissions_id&quot;)\n\tprivate DomainPermissions domainPermissions;\n\t\n\tpublic Users() {\n\t\tsuper();\n\t}\n\t\n\tpublic Users(String firstname, String lastname, DomainPermissions d) {\n\t\tsuper();\n\t\tthis.firstname = firstname;\n\t\tthis.lastname = lastname;\n\t\tthis.domainPermissions = d;\n\t}\n\/\/ getters + setters + toString()\n<\/pre><\/div>\n\n\n<p>As is seen, this class has a attribute with type of &#8220;<code>DomainPermissions<\/code>&#8221; and there is an OneToOne<strong> Bidirectional<\/strong> association between &#8220;<code>Users<\/code>&#8221; and &#8220;<code>DomainPermissions<\/code>&#8221; classes.<\/p>\n\n\n\n<p><strong>DomainPermissions Class:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\npublic class DomainPermissions {\n\t\n\t@Id\n\t@GeneratedValue\n\tprivate Long domainPermissions_id;\n\t\n\t@OneToOne(cascade = CascadeType.ALL, \n\t\t\torphanRemoval = true)\n\t@JoinColumn(name=&quot;customerDomain_permission_id&quot;, columnDefinition = &quot;bigint default 1&quot;)\n\tprivate Permission customerDomain;\n\t\n\t@OneToOne(cascade = CascadeType.ALL, \n\t\t\torphanRemoval = true)\n\t@JoinColumn(name=&quot;productDomain_permission_id&quot;, columnDefinition = &quot;bigint default 1&quot;)\n\tprivate Permission productDomain;\n\t\n\t@OneToOne(mappedBy = &quot;domainPermissions&quot;)\n\tprivate Users user;\n\n\/\/ getters + setters + toString()\n<\/pre><\/div>\n\n\n<p>And this &#8220;<code>DomainPermission<\/code>&#8221; class has 2 &#8220;<code>Permission<\/code>&#8221; super type attributes for available application domain types. Also, has OneToOne<strong> Unidirectinal<\/strong> association with &#8220;<code>Permission<\/code>&#8221; super type. In future when a new domain comes I can simply create another subtype and add another attribute in here such as:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n(...)\n@OneToOne(cascade = CascadeType.ALL, \n\t\t\torphanRemoval = true)\n\t@JoinColumn(name=&quot;blablaDomain_permission_id&quot;, columnDefinition = &quot;bigint default 1&quot;)\n\tprivate Permission blablaDomain;\n(...)\n<\/pre><\/div>\n\n\n<p>But an important thing is if a new subclass (domain) creation occurs in the future, a new null column will add to the &#8220;<code>DomainPermissions<\/code>&#8221; table and all of the before rows will mark at this column as null, this is an unwanted situation, so I had to pay attention for potential null pointer exceptions and Data Integrity. To prevent this I rearrange the DomainPermissions class and define a DEFAULT Constraint per domain such as:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n\t@JoinColumn(name=&quot;customerDomain_permission_id&quot;, columnDefinition = &quot;bigint default 1&quot;)\n         \/\/ private Permission some_domain_name;\n<\/pre><\/div>\n\n\n<p>In this notation the attribute with id 1 should be an all &#8220;false&#8221; responsive record placed on <code>Permission<\/code> class table and it stand in for null object pattern. This can be creating at the deployment or coding in a Servlet which takes care of initialization stuff.  <\/p>\n\n\n\n<p><strong>DomainPermissionsBuilder Class:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class DomainPermissionsBuilder {\n\t\n\tprivate Permission customerDomain;\n\tprivate Permission productDomain;\n\n\tpublic DomainPermissionsBuilder setCustomerDomain(Permission c) {\n\t\tthis.customerDomain = c != null ? c : new CustomerDomainPermission();\n\t\treturn this;\n\t}\n\t\n\tpublic DomainPermissionsBuilder setProductDomain(Permission p) {\n\t\tthis.productDomain = p != null ? p : new ProductDomainPermission();\n\t\treturn this;\n\t}\n\t\n\tpublic DomainPermissions build() {\n\t\tif (this.customerDomain == null)\n\t\t\tthis.customerDomain = new CustomerDomainPermission();\n\t\tif (this.productDomain == null)\n\t\t\tthis.productDomain = new ProductDomainPermission();\n\t\treturn new DomainPermissions(customerDomain, productDomain);\n\t}\n\t\n}\n<\/pre><\/div>\n\n\n<p><strong>Permission Class:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\n@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)\npublic class Permission {\n\t\n\t@Id\n\t@GeneratedValue\n\tLong permission_id;\n\t\n\t@Column(name = &quot;_create&quot;)\n\tprivate boolean _create;\n\t\n\t@Column(name = &quot;_read&quot;)\n\tprivate boolean _read;\n\t\n\t@Column(name = &quot;_update&quot;)\n\tprivate boolean _update;\n\t\n\t@Column(name = &quot;_delete&quot;)\n\tprivate boolean _delete;\n\t\t\t\n\tpublic Permission() {\n\t\tsuper();\n\t\tthis._create = false;\n\t\tthis._read = false;\n\t\tthis._update = false;\n\t\tthis._delete = false;\n\t}\n\n\tpublic Permission(boolean _create, boolean _read, boolean _update, boolean _delete) {\n\t\tsuper();\n\t\tthis._create = _create;\n\t\tthis._read = _read;\n\t\tthis._update = _update;\n\t\tthis._delete = _delete;\n\t}\ngetters + setters + toString()\n<\/pre><\/div>\n\n\n<p><strong>CustomerDomainPermission Class:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\npublic class CustomerDomainPermission extends Permission {\n\t\n\tpublic CustomerDomainPermission() {\n\t\tsuper();\n\t}\n}\n<\/pre><\/div>\n\n\n<p><strong>ProductDomainPermission Class:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@Entity\npublic class ProductDomainPermission extends Permission {\n\t\n\tpublic ProductDomainPermission() {\n\t\tsuper();\n\t}\n}\n<\/pre><\/div>\n\n\n<p><strong>JUnit Test:<\/strong><\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\nclass PermissionTest {\n\t\n\tUsers user;\n\tPermission cd;\n\tPermission pd;\n\tDomainPermissions d;\n\t\n\t@BeforeAll\n\tvoid createUser() {\n\t\tcd = new CustomerDomainPermission();\n\t\tcd.set_read(true);\n\t\tcd.set_create(false);\n\t\tcd.set_delete(false);\n\t\tcd.set_update(true);\n\t\t\n\t\tpd = new ProductDomainPermission();\n\t\t\t\t\n\t\td = new DomainPermissions();\n\t\td.setCustomerDomain(cd);\n\t\td.setProductDomain(pd);\n\t\t\n\t\tuser = new Users();\n\t\tuser.setFirstname(&quot;Alfred&quot;);\n\t\tuser.setLastname(&quot;Hitchcock&quot;);\n\t\tuser.setDomainPermissions(d);\n\t}\n\t\n\t@Test\n\t@DisplayName(&quot;When creating Customer Domain Permissions&quot;)\n\tvoid customerDomainPermissionsTest() {\n\t\tassertAll(\n\t\t\t\t() -&gt; assertEquals(false, user.getDomainPermissions().getCustomerDomain().is_create()),\n\t\t\t\t() -&gt; assertEquals(true, user.getDomainPermissions().getCustomerDomain().is_read()),\n\t\t\t\t() -&gt; assertEquals(true, user.getDomainPermissions().getCustomerDomain().is_update()),\n\t\t\t\t() -&gt; assertEquals(false, user.getDomainPermissions().getCustomerDomain().is_delete())\t\t\t\t\n\t\t\t\t);\n\t}\n\t\n\t@Test\n\t@DisplayName(&quot;When creating Product Domain Permissions&quot;)\n\tvoid productDomainPermissionsTest() {\n\t\tassertAll(\n\t\t\t\t() -&gt; assertEquals(false, user.getDomainPermissions().getProductDomain().is_create()),\n\t\t\t\t() -&gt; assertEquals(false, user.getDomainPermissions().getProductDomain().is_read()),\n\t\t\t\t() -&gt; assertEquals(false, user.getDomainPermissions().getProductDomain().is_update()),\n\t\t\t\t() -&gt; assertEquals(false, user.getDomainPermissions().getProductDomain().is_delete())\t\t\t\t\n\t\t\t\t);\n\t}\n\t\n\t@Test\n\t@DisplayName(&quot;Is CustomerDomainPermission an instance of correct sub class&quot;)\n\tvoid customerDomainPermissionInstantiationCheck() {\n\t\tassertTrue(cd instanceof CustomerDomainPermission);\n\t}\n\t\n\t@Test\n\t@DisplayName(&quot;Is ProductDomainPermission an instance of correct sub class&quot;)\n\tvoid productDomainPermissionInstantiationCheck() {\n\t\tassertTrue(pd instanceof ProductDomainPermission);\n\t}\n\t\n\t@Test\n\t@DisplayName(&quot;Does DomainPermissions Type Include CustomerDomainPermission&quot;)\n\tvoid domainPermissionsTypeCustomerDomainPermissionContentTest() {\n\t\tassertEquals(cd, d.getCustomerDomain());\n\t}\n\t\n\t@Test\n\t@DisplayName(&quot;Does DomainPermissions Type Include ProductDomainPermission&quot;)\n\tvoid domainPermissionTypeProductDomainPermissionContentTest() {\n\t\tassertEquals(pd, d.getProductDomain());\n\t}\n\t\n\t@Test\n\t@DisplayName(&quot;Does the User have correct DomainPermissions&quot;)\n\tvoid userDomainPermissionsTest() {\n\t\tassertEquals(d, user.getDomainPermissions());\n\t}\n<\/pre><\/div>\n\n\n<p><strong>Output:<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/junit01.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"717\" height=\"324\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/junit01.jpg\" alt=\"\" class=\"wp-image-420\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/junit01.jpg 717w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/junit01-300x136.jpg 300w\" sizes=\"(max-width: 717px) 100vw, 717px\" \/><\/a><figcaption>JUnit Test Result Screen<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Database Tables:<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-image size-large is-resized is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/allTables.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/allTables.jpg\" alt=\"\" class=\"wp-image-377\" width=\"620\" height=\"336\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/allTables.jpg 761w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/allTables-300x163.jpg 300w\" sizes=\"(max-width: 620px) 100vw, 620px\" \/><\/a><figcaption>All Tables<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-resized is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/users.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/users.jpg\" alt=\"\" class=\"wp-image-378\" width=\"636\" height=\"197\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/users.jpg 959w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/users-300x94.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/users-768x239.jpg 768w\" sizes=\"(max-width: 636px) 100vw, 636px\" \/><\/a><figcaption>Users Table<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-resized is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/DomainPermissions.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/DomainPermissions.jpg\" alt=\"\" class=\"wp-image-379\" width=\"641\" height=\"198\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/DomainPermissions.jpg 964w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/DomainPermissions-300x93.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/DomainPermissions-768x238.jpg 768w\" sizes=\"(max-width: 641px) 100vw, 641px\" \/><\/a><figcaption>DomainPermissions Table<\/figcaption><\/figure>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/permission-1.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"655\" height=\"207\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/permission-1.jpg\" alt=\"\" class=\"wp-image-436\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/permission-1.jpg 655w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/permission-1-300x95.jpg 300w\" sizes=\"(max-width: 655px) 100vw, 655px\" \/><\/a><figcaption>Permission Base Class Table<\/figcaption><\/figure>\n<\/div><\/div>\n<\/div><\/div>\n<\/div><\/div>\n<\/div><\/div>\n<\/div><\/div>\n\n\n\n<figure class=\"wp-block-image size-large is-resized is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/customerDomainPermission.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/customerDomainPermission.jpg\" alt=\"\" class=\"wp-image-381\" width=\"627\" height=\"196\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/customerDomainPermission.jpg 964w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/customerDomainPermission-300x94.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/customerDomainPermission-768x241.jpg 768w\" sizes=\"(max-width: 627px) 100vw, 627px\" \/><\/a><figcaption>CustomerDomainPermission Table<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large is-resized is-style-default\"><a href=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/productDomainPermission.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blog.gunlerveisler.gen.tr\/wp-content\/uploads\/2020\/08\/productDomainPermission.jpg\" alt=\"\" class=\"wp-image-382\" width=\"602\" height=\"172\" srcset=\"https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/productDomainPermission.jpg 938w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/productDomainPermission-300x86.jpg 300w, https:\/\/aliyargunes.com.tr\/blog\/wp-content\/uploads\/2020\/08\/productDomainPermission-768x221.jpg 768w\" sizes=\"(max-width: 602px) 100vw, 602px\" \/><\/a><figcaption>ProductDomainPermission Table<\/figcaption><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here is an idea for managing the user permissions at my web app. In this design users have different privileges to perform basic crud operations on different app domains (Customer Management Domain, Stock Management Domain etc.). In this way, some &hellip; <a href=\"https:\/\/aliyargunes.com.tr\/blog\/about-my-abortive-design\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,13,7],"tags":[78,79,66,43,76,70,77,75],"class_list":["post-287","post","type-post","status-publish","format-standard","hentry","category-projects","category-software-architecture","category-techlog","tag-composition","tag-database-normalization","tag-hibernate-5","tag-mysql","tag-object-oriented-programming","tag-polymorphism","tag-solid","tag-user-permission-design"],"_links":{"self":[{"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/posts\/287"}],"collection":[{"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/comments?post=287"}],"version-history":[{"count":113,"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/posts\/287\/revisions"}],"predecessor-version":[{"id":895,"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/posts\/287\/revisions\/895"}],"wp:attachment":[{"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/media?parent=287"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/categories?post=287"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/aliyargunes.com.tr\/blog\/wp-json\/wp\/v2\/tags?post=287"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}