Tutorials

Labels
AJAX(112) App Studio(7) Apple(1) Application Builder(245) Application Factory(207) ASP.NET(95) ASP.NET 3.5(45) ASP.NET Code Generator(72) ASP.NET Membership(28) Azure(18) Barcode(2) Barcodes(3) BLOB(18) Business Rules(1) Business Rules/Logic(140) BYOD(13) Caching(2) Calendar(5) Charts(29) Cloud(14) Cloud On Time(2) Cloud On Time for Windows 7(2) Code Generator(54) Collaboration(11) command line(1) Conflict Detection(1) Content Management System(12) COT Tools for Excel(26) CRUD(1) Custom Actions(1) Data Aquarium Framework(122) Data Sheet(9) Data Sources(22) Database Lookups(50) Deployment(22) Designer(177) Device(1) DotNetNuke(12) EASE(20) Email(6) Features(101) Firebird(1) Form Builder(14) Globalization and Localization(6) How To(1) Hypermedia(2) Inline Editing(1) Installation(5) JavaScript(20) Kiosk(1) Low Code(3) Mac(1) Many-To-Many(4) Maps(6) Master/Detail(36) Microservices(4) Mobile(63) Mode Builder(3) Model Builder(3) MySQL(10) Native Apps(5) News(18) OAuth(9) OAuth Scopes(1) OAuth2(13) Offline(20) Offline Apps(4) Offline Sync(5) Oracle(11) PKCE(2) Postgre SQL(1) PostgreSQL(2) PWA(2) QR codes(2) Rapid Application Development(5) Reading Pane(2) Release Notes(183) Reports(48) REST(29) RESTful(29) RESTful Workshop(15) RFID tags(1) SaaS(7) Security(81) SharePoint(12) SPA(6) SQL Anywhere(3) SQL Server(26) SSO(1) Stored Procedure(4) Teamwork(15) Tips and Tricks(87) Tools for Excel(2) Touch UI(93) Transactions(5) Tutorials(183) Universal Windows Platform(3) User Interface(338) Video Tutorial(37) Web 2.0(100) Web App Generator(101) Web Application Generator(607) Web Form Builder(40) Web.Config(9) Workflow(28)
Archive
Blog
Tutorials
Tuesday, November 27, 2012PrintSubscribe
Advanced User Manager for Custom Membership and Role Provider: Adding “Roles” and “Confirm Password” Fields

Let’s add two calculated fields to Users controller. Roles field will allow app users to change role assignments for a user. Confirm Password field will require the app user to write the password twice when creating a user.

Adding “Roles”

In the Project Explorer, switch to the Controllers tab. Right-click on Users / Fields node, and press New Field.

'New Field' context menu option for Users controller.

Assign the following values:

Property Value
Name Roles
Type String
Length 255
Allow null values. true
The value of this field is computed at run-time by SQL expression. true
Label Roles
Items Style Check Box List
Items Data Controller Roles
Data Value Field RoleName
Data Text Field RoleName

Press OK to save the field.

Drop Users / Fields /Roles (String(255)) –> Roles: RoleName / RoleName field node onto Users / Views / editForm1 / c1 – User Information category node to create a data field at the end.

Dropping 'Roles' field onto a category in 'editForm1' to create a data field.     'Roles' data field created in 'editForm1' view.

Drop Roles data field node on the right side of UserName node to place it after UserName.

Dropping Roles data field on the right side of UserName to place it second in the category.     Roles data field is now second in the category.

Drop Users / Fields / Roles (String(255)) –> Roles: RoleName / RoleName node onto Users / Views / createForm1 / c2 – Roles category node.

Dropping 'Roles' field onto a category in 'createForm1' to create a data field.     'Roles' data field created in 'createForm1' view.

Handling Roles Field

The Roles field has been added to the form, but it will not be populated. Let’s create a business rule to populate values. In the Project Explorer, right-click on Users / Business Rules node, and press New Business Rule.

Creating a new business rule for Users controller.

Property Value
Type C# / Visual Basic
Command Name Select
View editForm1
Phase Execute

Save the rule. On the toolbar, press Browse to regenerate the web app and create the business rule file. When finished, right-click on Users / Business Rules / Select (Code / Before) – r100 node and press Edit Rule in Visual Studio.

Context menu option 'Edit Rule in Visual Studio' for a business rule.

Replace the code with the following.

C#:

using System;
using System.Data;
using System.Text;
using MyCompany.Data;

namespace MyCompany.Rules
{
    public partial class UsersBusinessRules : MyCompany.Data.BusinessRules
    {

        /// <summary>
        /// This method will execute in the view with id matching "editForm1" for an action
        /// with a command name that matches "Select".
        /// </summary>
        [Rule("r100")]
        public void r100Implementation(
                    FieldValue userID,
                    string userName,
                    string password,
                    string email,
                    string comment,
                    string passwordQuestion,
                    string passwordAnswer,
                    bool? isApproved,
                    DateTime? lastActivityDate,
                    DateTime? lastLoginDate,
                    DateTime? lastPasswordChangedDate,
                    DateTime? creationDate,
                    bool? isLockedOut,
                    DateTime? lastLockedOutDate,
                    int? failedPasswordAttemptCount,
                    DateTime? failedPasswordAttemptWindowStart,
                    int? failedPasswordAnswerAttemptCount,
                    DateTime? failedPasswordAnswerAttemptWindowStart,
                    string confirmPassword,
                    string roles)
        {
            // concatenate user roles in comma-separated list
            StringBuilder sb = new StringBuilder();
            foreach (string role in System.Web.Security.Roles.GetRolesForUser(userName))
            {
                if (sb.Length > 0)
                    sb.Append(',');
                sb.Append(role);
            }
            // store the list of roles to the "Roles" field
            UpdateFieldValue("Roles", sb.ToString());
        }
    }
}

Visual Basic:

Imports MyCompany.Data
Imports System
Imports System.Linq

Namespace MyCompany.Rules
    
    Partial Public Class UsersBusinessRules
        Inherits MyCompany.Data.BusinessRules
        
        ''' <summary>
        ''' This method will execute in any view before an action
        ''' with a command name that matches "Select" and argument that matches "editForm1".
        ''' </summary>
        <Rule("r100")> _
        Public Sub r100Implementation( _
                    ByVal userID As FieldValue, _
                    ByVal userName As String, _
                    ByVal password As String, _
                    ByVal email As String, _
                    ByVal comment As String, _
                    ByVal passwordQuestion As String, _
                    ByVal passwordAnswer As String, _
                    ByVal isApproved As Nullable(Of Boolean), _
                    ByVal lastActivityDate As Nullable(Of DateTime), _
                    ByVal lastLoginDate As Nullable(Of DateTime), _
                    ByVal lastPasswordChangedDate As Nullable(Of DateTime), _
                    ByVal creationDate As Nullable(Of DateTime), _
                    ByVal isLockedOut As Nullable(Of Boolean), _
                    ByVal lastLockedOutDate As Nullable(Of DateTime), _
                    ByVal failedPasswordAttemptCount As Nullable(Of Integer), _
                    ByVal failedPasswordAttemptWindowStart As Nullable(Of DateTime), _
                    ByVal failedPasswordAnswerAttemptCount As Nullable(Of Integer), _
                    ByVal failedPasswordAnswerAttemptWindowStart As Nullable(Of DateTime), _
                    ByVal roles As String, _
                    ByVal confirmPassword As String, _
                    ByVal roleID As Nullable(Of Integer))
            ' concatenate user roles in comma-separated list
            Dim sb As New StringBuilder()
            For Each role As String In System.Web.Security.Roles.GetRolesForUser(userName)
                If (sb.Length > 0) Then
                    sb.Append(",")
                End If
                sb.Append(role)
            Next
            ' store the list of roles to the "Roles" field
            UpdateFieldValue("Roles", sb.ToString())
        End Sub
    End Class
End Namespace

Save the business rule file.

Adding “Confirm Password”

Right-click on Users / Fields node, and press New Field.

Creating a new field in Users controller.

Assign the following:

Property Value
Name ConfirmPassword
Type String
Length 40
The value of this field is calculated by a business rule expression. true
Label Confirm Password

Press OK to save the field. Drop Users / Fields / ConfirmPassword* (String(40)) onto Users / Views / createForm1 / c1 – New User Information category node to create a data field.

Dropping 'ConfirmPassword' field onto a category in 'createForm1' to create a data field.     'ConfirmPassword' data field created in 'createForm1' view.

Drop ConfirmPassword data field on the right side of Password to place it in the third position in the category.

Dropping ConfirmPassword data field node on the right side of Password.    ConfirmPassword data field is now in the third position.

Double-click on Users / Views / createForm1 / c1 – New User Information / ConfirmPassword data field node. Make the following change:

Property New Value
Text Mode Password

Press OK to save.

Tuesday, November 27, 2012PrintSubscribe
Advanced User Manager for Custom Membership and Role Provider: Configuring the Views

Let’s customize the Users page and views in order to improve the presentation of the User Management screen.

Moving the Users Page

Start the Project Designer. In the Project Explorer, drag Region / Roles page node onto Region / Users page node to place it underneath Users page.

Dropping Roles page node onto Users page node.      Roles page node has been placed underneath Users page.

Drag Region / Users node on the right side of Reports node to place it at the bottom of the hierarchy.

Dropping Users page node on the right side of Reports page node.      Users page has been placed after Reports.

Right-click on Users / container2 node, and press Delete.

Deleting 'container2' on the Users page.

Configuring grid1

Switch to the Controllers tab and expand to Users / Views / grid1 node. While holding Ctrl key, select the data fields in the following order: UserName, IsApproved, Email, IsLockedOut, CreationDate, LastLoginDate, and Comment. Drop the data fields on Users / Views / grid1 to sort the fields in the selected order.

Dropping several data fields onto 'grid1' view.      The data fields have been rearranged.

Select the data fields LastActivityDate and LastLockedOutDate. Right-click and press Delete.

Deleteing data fields 'LastActivityDate' and 'LastLockedOutDate'.

Configuring editForm1

Double-click on Users / Views / editForm1 / c1 – Users category node.

The category 'c1 - Users' of editForm1 view.

Change the following properties:

Property New Value
Header Text User Information
Description Please select user roles that most closely match user's responsibilities. Roles control access to the areas of this web site. Please contact system administrator if role access restrictions must be changed. Enter any additional comments about this user account. Comment is not visible to the user.

Press OK to save. Right-click on Users / Views / editForm1 node, and press New Category.

New Category context mneu option for editForm1 view.

Assign the following values:

Property New Value
Header Text Password Recovery
Description During the recovery of a forgotten password the user will be asked to enter a user name. If a user account exists then a security question is requested to be answered. A correct answer will trigger an email with a temporary password send to the user. Change locked out flag to 'No' if the user has been locked out after reaching a maximum number of failed login attempts and you want to allow user to login again.

Press OK to save. Expand Users / Views / editForm1 / c1 – User Information category node. While holding Ctrl key, select the following data fields: Email, Password Question, and IsLockedOut. Drop the data fields onto Users / Views / editForm1 / c2 – Password Recovery node.

Dropping several data fields onto category 'c2 - Password Recovery'.      Data fields have been moved to category 'c2 - Password Recovery'.

Press OK to save. Create another category with these properties:

Property New Value
Header Text Activity Statistics
Description Shows statistics of user activity.

Save the category. Drag the data fields CreationDate, LastLoginDate, LastActivityDate, and LastPasswordChangedDate onto Users / Views / editForm1 / c3 – Activity Statistics.

Dropping several data fields onto category 'c3 - Activity Statistics'.      Data fields have been moved to category 'c3 - Activity Statistics'.

Create one more category:

Property New Value
Header Text Login Statistics
Description These are the statistics of failed login attempts by this user. User will be locked out after reaching a maximum number of failed login attempts. Locked out users will be able to login again after the date in Failed Password Attempt Window Start. Users who failed to recover the password will be able to so after the date in Failed Password Answer Attempt Window Start. You can restore user's ability to login by setting Locked Out flag to 'No'.

Save the category. Drag the data fields LastLockedOutDate, FailedPasswordAttemptCount, FailedPasswordAttemptWindowStart, FailedPasswordAnswerAttemptCount, and FailedPasswordAnswerAttemptWindowStart onto Users / Views / editForm1 / c4 – Login Statistics category node.

Dropping several data fields onto category 'c4 - Login Statistics'.      Data fields have been moved to category 'c4 - Login Statistics'.

Select the data fields Password and PasswordAnswer. Right-click, and press Delete.

Deleting the data fields 'Password' and 'PasswordAnswer'.

Configuring createForm1

Double-click on Users / Views / createForm1 / c1 – New Users category node.

Category 'c1 - New Users' of createForm1 view.

Change the following properties:

Property New Value
Header Text New User Information
Description Please enter user name and password. Note that password must be at least 7 characters long and include one non-alphanumeric character. Only approved users will be able to login into the website.

Press OK to save. Right-click on Users / Views / createForm1 node, and press New Category.

New Category context mneu option for 'createForm1' view.

Assign the following values:

Property New Value
Header Text Roles
Description Please select user roles that most closely match user's responsibilities. Roles control access to the areas of this web site. Please contact system administrator if role access restrictions must be changed.

Press OK to save. The Roles field will be added in the next tutorial.

Create another category with these properties:

Property New Value
Header Text Password Recovery
Description These fields are required to help a user to recover a forgotten password. During the recovery process the user will be asked to enter a user name. If a user account exists then a security question is requested to be answered. A correct answer will trigger an email with a temporary password send to the user.

Save the category. Drag the data fields Email, PasswordQuestion, and PasswordAnswer onto Users / Views / createForm1 / c3 – Password Recovery.

Dropping several data fields onto category 'c3 - Password Recovery'.     Data fields moved to category 'c3 - Password Recovery'.

Create one more category:

Property New Value
Header Text Comments
Description Enter any additional comments about this user account. Comment is not visible to the user.

Save the category. Drag the data field Comment onto Users / Views / createForm1 / c4 – Comments category node.

Several data fields dropped onto category 'c4 - Comments'.     Data fields moved to category 'c4 - Comments'.

Click on the data field LastActivityDate. While holding Shift key, click on the data field FailedPasswordAnswerAttemptWindowStart. Right-click, and press Delete.

Deleting the unnecessary data fields from createForm1 view.

Configuring Read-Only Fields and Checkboxes

Right-click on Users / Fields node, and press List.

The 'List' option for Fields node of Users controller.

Make the following changes to the list of fields:

Name Read Only Items Style Data Format String
IsApproved   Check Box  
LastActivityDate Yes   g
LastLoginDate Yes   g
LastPasswordChangedDate Yes   g
CreationDate Yes   g
IsLockedOut   Check Box  
LastLockedOutDate Yes   g
FailedPasswordAttemptCount Yes    
FailedPasswordAttemptWindowStart Yes   g
FailedPasswordAnswerAttemptCount Yes    
FailedPasswordAnswerAttemptWindowStart Yes   g

Double-click on Users / Views / editForm1 / c1 – User Information / UserName data field.

UserName data field node of 'editForm1' of Users controller.

Change the Read Only property:

Property New Value
Read Only Yes

Press OK to save. Double-click on Users / Views / editForm1 / c2 – Password Recovery / PasswordQuestion data field.

PasswordQuestion data field node of 'editForm1' of Users controller.

Change the Read Only property:

Property New Value
Read Only Yes

Press OK to save. Double-click on Users / Views / createForm1 / c1 – New User Information / Password data field node. Make the following change:

Property New Value
Text Mode Password

Save the data field.

Friday, November 9, 2012PrintSubscribe
Advanced Membership Provider for MySQL

Requirements

An advanced membership and role provider requires three tables.

One table keeps track of user information. This information includes the UserName, Email, and a Comment. Additional columns allow for implementation of a password question and answer in order to recover a forgotten password. When users are created, they can not be approved by default. Additional information is captured about the most recent login, activity, and change of password. When a user inputs an incorrect password past the limit, the user will become locked out. The number of failed attempts and most recent failed attempt will be stored.

Two tables are required to keep track of roles and associations of users with roles.

These are the advanced membership and role provider tables with “identity” primary keys.

Advanced membership provider for MySQL with integer primary keys.

SQL:

create table Users (
    UserID int not null AUTO_INCREMENT primary key,
    UserName varchar(128) not null,
    Password varchar(128) not null,
    Email varchar(256),
    `Comment` text,
    PasswordQuestion varchar(256),
    PasswordAnswer varchar(128),
    IsApproved bit not null,
    LastActivityDate datetime not null,
    LastLoginDate datetime not null,
    LastPasswordChangedDate datetime not null,
    CreationDate datetime not null,
    IsLockedOut bit not null,
    LastLockedOutDate datetime not null,
    FailedPasswordAttemptCount int not null,
    FailedPasswordAttemptWindowStart datetime not null,
    FailedPasswordAnswerAttemptCount int not null,
    FailedPasswordAnswerAttemptWindowStart datetime not null
    );
    
create table Roles (
    RoleID int not null AUTO_INCREMENT primary key,
    RoleName varchar(128) not null
    );
create table UserRoles (
    UserID int not null,
    RoleID int not null,
    primary key (UserID, RoleID),
    foreign key (UserID) references Users(UserID),
    foreign key (RoleID) references Roles(RoleID)
    );

These are the advanced membership and role provider tables with “unique identifier” primary keys.

Advanced membership provider for MySQL with unique identifier primary keys.

SQL:

create table Users (
    UserID varchar(36) not null primary key default '',
    UserName varchar(128) not null,
    Password varchar(128) not null,
    Email varchar(256),
    `Comment` text,
    PasswordQuestion varchar(256),
    PasswordAnswer varchar(128),
    IsApproved bit not null,
    LastActivityDate datetime not null,
    LastLoginDate datetime not null,
    LastPasswordChangedDate datetime not null,
    CreationDate datetime not null,
    IsLockedOut bit not null,
    LastLockedOutDate datetime not null,
    FailedPasswordAttemptCount int not null,
    FailedPasswordAttemptWindowStart datetime not null,
    FailedPasswordAnswerAttemptCount int not null,
    FailedPasswordAnswerAttemptWindowStart datetime not null
    );
    
create table Roles (
    RoleID varchar(36) not null primary key default '',
    RoleName varchar(128) not null
    );
    
create table UserRoles (
    UserID varchar(36) not null,
    RoleID varchar(36) not null,
    primary key (UserID, RoleID),
    foreign key (UserID) references Users(UserID),
    foreign key (RoleID) references Roles(RoleID)
    );
delimiter $$ create trigger userinsert before insert on Users for each row begin set New.UserID = UUID(); end $$ create trigger roleinsert before insert on Roles for each row begin set New.RoleID = UUID(); end $$

Configuration

Use one of the scripts above to create the membership and role provider tables in your database.

Start Code On Time web application generator, select the project name on the start page, and choose Settings. Select Authentication and Membership.

Select “Enable custom membership and role providers” option and enter the following configuration settings.

table Users = Users
column [int|uiid] UserID = UserID
column [text] UserName = UserName
column [text] Password = Password
column [text] Email = Email
column [text] Comment = Comment
column [text] PasswordQuestion = PasswordQuestion
column [text] PasswordAnswer = PasswordAnswer
column [bool] IsApproved = IsApproved
column [date] LastActivityDate = LastActivityDate
column [date] LastLoginDate = LastLoginDate
column [date] LastPasswordChangedDate = LastPasswordChangedDate
column [date] CreationDate = CreationDate
column [bool] IsLockedOut = IsLockedOut
column [date] LastLockedOutDate = LastLockedOutDate
column [int] FailedPasswordAttemptCount = FailedPasswordAttemptCount
column [date] FailedPasswordAttemptWindowStart = FailedPasswordAttemptWindowStart
column [int] FailedPasswordAnswerAttemptCount = FailedPasswordAnswerAttemptCount
column [date] FailedPasswordAnswerAttemptWindowStart = FailedPasswordAnswerAttemptWindowStart

table Roles = Roles
column [int|uiid] RoleID = RoleID
column [text] RoleName = RoleName

table UserRoles = UserRoles
column [int|uiid] UserID = UserID
column [int|uiid] RoleID = RoleID

The configuration will guide the code generator in mapping the logical tables Users, Roles, and UserRoles to the physical tables in the database.

Generate the project to create the custom membership and role provider.