diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2009-11-13 17:04:21 -0800 |
---|---|---|
committer | Andrew Arnott <andrewarnott@gmail.com> | 2009-11-13 17:04:21 -0800 |
commit | e778892f1d9bf964c30ba6a10e50aedf12c2e857 (patch) | |
tree | 73ef8790efd0348348fb64e6cf8d438932635016 /projecttemplates/RelyingPartyLogic | |
parent | 888abd61a54576ff244533693df77f174f03c2bb (diff) | |
download | DotNetOpenAuth-e778892f1d9bf964c30ba6a10e50aedf12c2e857.zip DotNetOpenAuth-e778892f1d9bf964c30ba6a10e50aedf12c2e857.tar.gz DotNetOpenAuth-e778892f1d9bf964c30ba6a10e50aedf12c2e857.tar.bz2 |
Moved all the project template logic that would be common between MVC and web forms web sites into its own library.
Diffstat (limited to 'projecttemplates/RelyingPartyLogic')
21 files changed, 3111 insertions, 0 deletions
diff --git a/projecttemplates/RelyingPartyLogic/CreateDatabase.sql b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql new file mode 100644 index 0000000..52ca669 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/CreateDatabase.sql @@ -0,0 +1,197 @@ +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +CREATE TABLE [dbo].[Consumer]( + [ConsumerId] [int] IDENTITY(1,1) NOT NULL, + [ConsumerKey] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, + [ConsumerSecret] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [X509Certificate] [image] NULL, + [Callback] [nvarchar](2048) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [VerificationCodeFormat] [int] NOT NULL, + [VerificationCodeLength] [int] NOT NULL, + [Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT [PK_Consumer] PRIMARY KEY CLUSTERED +( + [ConsumerId] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] +GO +CREATE UNIQUE NONCLUSTERED INDEX [IX_Consumer] ON [dbo].[Consumer] +( + [ConsumerKey] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +CREATE TABLE [dbo].[User]( + [Id] [int] IDENTITY(1,1) NOT NULL, + [FirstName] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [LastName] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [EmailAddress] [nvarchar](100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [EmailAddressVerified] [bit] NOT NULL, + CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] +GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +CREATE TABLE [dbo].[Role]( + [Id] [int] IDENTITY(1,1) NOT NULL, + [Name] [nvarchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, + CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] +GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +SET ANSI_PADDING ON +GO +CREATE TABLE [dbo].[IssuedToken]( + [TokenId] [int] IDENTITY(1,1) NOT NULL, + [ConsumerId] [int] NOT NULL, + [UserId] [int] NULL, + [Token] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, + [TokenSecret] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, + [CreatedOn] [datetime] NOT NULL, + [Callback] [nvarchar](2048) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [VerificationCode] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [ConsumerVersion] [varchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + [ExpirationDate] [datetime] NULL, + [IsAccessToken] [bit] NOT NULL, + [Scope] [nvarchar](255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT [PK_IssuedToken] PRIMARY KEY CLUSTERED +( + [TokenId] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] +GO +SET ANSI_PADDING OFF +GO +CREATE UNIQUE NONCLUSTERED INDEX [IX_IssuedToken] ON [dbo].[IssuedToken] +( + [Token] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +CREATE TABLE [dbo].[UserRole]( + [UserId] [int] NOT NULL, + [RoleId] [int] NOT NULL, + CONSTRAINT [PK_UserRole] PRIMARY KEY CLUSTERED +( + [UserId] ASC, + [RoleId] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] +GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +CREATE TABLE [dbo].[AuthenticationToken]( + [Id] [int] IDENTITY(1,1) NOT NULL, + [UserId] [int] NOT NULL, + [OpenIdClaimedIdentifier] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CS_AS NOT NULL, + [OpenIdFriendlyIdentifier] [nvarchar](250) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, + CONSTRAINT [PK_AuthenticationToken] PRIMARY KEY CLUSTERED +( + [Id] ASC +)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] +) ON [PRIMARY] +GO +SET ANSI_NULLS ON +GO +SET QUOTED_IDENTIFIER ON +GO +CREATE PROCEDURE [dbo].[AddUser] + ( + @firstName nvarchar(50), + @lastName nvarchar(50), + @openid nvarchar(255), + @role nvarchar(255) + ) +AS + DECLARE + @roleid int, + @userid int + + BEGIN TRANSACTION + + INSERT INTO [dbo].[User] (FirstName, LastName) VALUES (@firstName, @lastName) + SET @userid = (SELECT @@IDENTITY) + + IF (SELECT COUNT(*) FROM dbo.Role WHERE [Name] = @role) = 0 + BEGIN + INSERT INTO dbo.Role (Name) VALUES (@role) + SET @roleid = (SELECT @@IDENTITY) + END + ELSE + BEGIN + SET @roleid = (SELECT Id FROM dbo.Role WHERE [Name] = @role) + END + + INSERT INTO dbo.UserRole (UserId, RoleId) VALUES (@userId, @roleid) + + INSERT INTO dbo.AuthenticationToken + (UserId, OpenIdClaimedIdentifier, OpenIdFriendlyIdentifier) + VALUES + (@userid, @openid, @openid) + + COMMIT TRANSACTION + + RETURN @userid +GO +ALTER TABLE [dbo].[User] ADD CONSTRAINT [DF_User_EmailAddressVerified] DEFAULT ((0)) FOR [EmailAddressVerified] +GO +ALTER TABLE [dbo].[IssuedToken] ADD CONSTRAINT [DF_IssuedToken_CreatedOn] DEFAULT (getdate()) FOR [CreatedOn] +GO +ALTER TABLE [dbo].[IssuedToken] ADD CONSTRAINT [DF_IssuedToken_IsAccessToken] DEFAULT ((0)) FOR [IsAccessToken] +GO +ALTER TABLE [dbo].[IssuedToken] WITH CHECK ADD CONSTRAINT [FK_IssuedToken_Consumer] FOREIGN KEY([ConsumerId]) +REFERENCES [dbo].[Consumer] ([ConsumerId]) +ON UPDATE CASCADE +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[IssuedToken] CHECK CONSTRAINT [FK_IssuedToken_Consumer] +GO +ALTER TABLE [dbo].[IssuedToken] WITH CHECK ADD CONSTRAINT [FK_IssuedToken_User] FOREIGN KEY([UserId]) +REFERENCES [dbo].[User] ([Id]) +ON UPDATE CASCADE +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[IssuedToken] CHECK CONSTRAINT [FK_IssuedToken_User] +GO +ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_Role] FOREIGN KEY([RoleId]) +REFERENCES [dbo].[Role] ([Id]) +ON UPDATE CASCADE +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[UserRole] CHECK CONSTRAINT [FK_UserRole_Role] +GO +ALTER TABLE [dbo].[UserRole] WITH CHECK ADD CONSTRAINT [FK_UserRole_User] FOREIGN KEY([UserId]) +REFERENCES [dbo].[User] ([Id]) +ON UPDATE CASCADE +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[UserRole] CHECK CONSTRAINT [FK_UserRole_User] +GO +ALTER TABLE [dbo].[AuthenticationToken] WITH CHECK ADD CONSTRAINT [FK_AuthenticationToken_User] FOREIGN KEY([UserId]) +REFERENCES [dbo].[User] ([Id]) +ON UPDATE CASCADE +ON DELETE CASCADE +GO +ALTER TABLE [dbo].[AuthenticationToken] CHECK CONSTRAINT [FK_AuthenticationToken_User] +GO diff --git a/projecttemplates/RelyingPartyLogic/DataRoleProvider.cs b/projecttemplates/RelyingPartyLogic/DataRoleProvider.cs new file mode 100644 index 0000000..1171646 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/DataRoleProvider.cs @@ -0,0 +1,123 @@ +//----------------------------------------------------------------------- +// <copyright file="DataRoleProvider.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using System.Web.Security; + + public class DataRoleProvider : RoleProvider { + public override string ApplicationName { + get { throw new NotImplementedException(); } + set { throw new NotImplementedException(); } + } + + public override void AddUsersToRoles(string[] usernames, string[] roleNames) { + var users = from token in Database.DataContext.AuthenticationToken + where usernames.Contains(token.ClaimedIdentifier) + select token.User; + var roles = from role in Database.DataContext.Role + where roleNames.Contains(role.Name, StringComparer.OrdinalIgnoreCase) + select role; + foreach (User user in users) { + foreach (Role role in roles) { + user.Roles.Add(role); + } + } + } + + public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) { + var users = from token in Database.DataContext.AuthenticationToken + where usernames.Contains(token.ClaimedIdentifier) + select token.User; + var roles = from role in Database.DataContext.Role + where roleNames.Contains(role.Name, StringComparer.OrdinalIgnoreCase) + select role; + foreach (User user in users) { + foreach (Role role in roles) { + user.Roles.Remove(role); + } + } + } + + public override void CreateRole(string roleName) { + Database.DataContext.AddToRole(new Role { Name = roleName }); + } + + /// <summary> + /// Removes a role from the data source for the configured applicationName. + /// </summary> + /// <param name="roleName">The name of the role to delete.</param> + /// <param name="throwOnPopulatedRole">If true, throw an exception if <paramref name="roleName"/> has one or more members and do not delete <paramref name="roleName"/>.</param> + /// <returns> + /// true if the role was successfully deleted; otherwise, false. + /// </returns> + public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) { + Role role = Database.DataContext.Role.SingleOrDefault(r => r.Name == roleName); + if (role == null) { + return false; + } + + if (throwOnPopulatedRole && role.Users.Count > 0) { + throw new InvalidOperationException(); + } + + Database.DataContext.DeleteObject(roleName); + return true; + } + + /// <summary> + /// Gets an array of user names in a role where the user name contains the specified user name to match. + /// </summary> + /// <param name="roleName">The role to search in.</param> + /// <param name="usernameToMatch">The user name to search for.</param> + /// <returns> + /// A string array containing the names of all the users where the user name matches <paramref name="usernameToMatch"/> and the user is a member of the specified role. + /// </returns> + public override string[] FindUsersInRole(string roleName, string usernameToMatch) { + return (from role in Database.DataContext.Role + where role.Name == roleName + from user in role.Users + from authTokens in user.AuthenticationTokens + where authTokens.ClaimedIdentifier == usernameToMatch + select authTokens.ClaimedIdentifier).ToArray(); + } + + public override string[] GetAllRoles() { + return Database.DataContext.Role.Select(role => role.Name).ToArray(); + } + + public override string[] GetRolesForUser(string username) { + return (from authToken in Database.DataContext.AuthenticationToken + where authToken.ClaimedIdentifier == username + from role in authToken.User.Roles + select role.Name).ToArray(); + } + + public override string[] GetUsersInRole(string roleName) { + return (from role in Database.DataContext.Role + where string.Equals(role.Name, roleName, StringComparison.OrdinalIgnoreCase) + from user in role.Users + from token in user.AuthenticationTokens + select token.ClaimedIdentifier).ToArray(); + } + + public override bool IsUserInRole(string username, string roleName) { + Role role = Database.DataContext.Role.SingleOrDefault(r => string.Equals(r.Name, roleName, StringComparison.OrdinalIgnoreCase)); + if (role != null) { + return role.Users.Any(user => user.AuthenticationTokens.Any(token => token.ClaimedIdentifier == username)); + } + + return false; + } + + public override bool RoleExists(string roleName) { + return Database.DataContext.Role.Any(role => string.Equals(role.Name, roleName, StringComparison.OrdinalIgnoreCase)); + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/Database.cs b/projecttemplates/RelyingPartyLogic/Database.cs new file mode 100644 index 0000000..a1e17a6 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Database.cs @@ -0,0 +1,150 @@ +//----------------------------------------------------------------------- +// <copyright file="Database.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Data; + using System.Data.SqlClient; + using System.Linq; + using System.ServiceModel; + using System.Text; + using System.Web; + + public class Database : IHttpModule, IDisposable { + private const string DataContextKey = "DataContext"; + + private const string DataContextTransactionKey = "DataContextTransaction"; + + /// <summary> + /// Initializes a new instance of the <see cref="Database"/> class. + /// </summary> + public Database() { + } + + public static User LoggedInUser { + get { return DataContext.AuthenticationToken.Where(token => token.ClaimedIdentifier == HttpContext.Current.User.Identity.Name).Select(token => token.User).FirstOrDefault(); } + } + + /// <summary> + /// Gets the transaction-protected database connection for the current request. + /// </summary> + public static DatabaseEntities DataContext { + get { + DatabaseEntities dataContext = DataContextSimple; + if (dataContext == null) { + dataContext = new DatabaseEntities(); + try { + dataContext.Connection.Open(); + } catch (EntityException entityEx) { + var sqlEx = entityEx.InnerException as SqlException; + if (sqlEx != null) { + if (sqlEx.Class == 14 && sqlEx.Number == 15350) { + // Most likely the database schema hasn't been created yet. + HttpContext.Current.Response.Redirect("~/Setup.aspx"); + } + } + + throw; + } + + DataContextTransactionSimple = dataContext.Connection.BeginTransaction(); + DataContextSimple = dataContext; + } + + return dataContext; + } + } + + private static DatabaseEntities DataContextSimple { + get { + if (HttpContext.Current != null) { + return HttpContext.Current.Items[DataContextKey] as DatabaseEntities; + } else if (OperationContext.Current != null) { + object data; + if (OperationContext.Current.IncomingMessageProperties.TryGetValue(DataContextKey, out data)) { + return data as DatabaseEntities; + } else { + return null; + } + } else { + throw new InvalidOperationException(); + } + } + + set { + if (HttpContext.Current != null) { + HttpContext.Current.Items[DataContextKey] = value; + } else if (OperationContext.Current != null) { + OperationContext.Current.IncomingMessageProperties[DataContextKey] = value; + } else { + throw new InvalidOperationException(); + } + } + } + + private static IDbTransaction DataContextTransactionSimple { + get { + if (HttpContext.Current != null) { + return HttpContext.Current.Items[DataContextTransactionKey] as IDbTransaction; + } else if (OperationContext.Current != null) { + object data; + if (OperationContext.Current.IncomingMessageProperties.TryGetValue(DataContextTransactionKey, out data)) { + return data as IDbTransaction; + } else { + return null; + } + } else { + throw new InvalidOperationException(); + } + } + + set { + if (HttpContext.Current != null) { + HttpContext.Current.Items[DataContextTransactionKey] = value; + } else if (OperationContext.Current != null) { + OperationContext.Current.IncomingMessageProperties[DataContextTransactionKey] = value; + } else { + throw new InvalidOperationException(); + } + } + } + + public void Dispose() { + } + + void IHttpModule.Init(HttpApplication context) { + context.EndRequest += this.Application_EndRequest; + context.Error += this.Application_Error; + } + + protected void Application_EndRequest(object sender, EventArgs e) { + CommitAndCloseDatabaseIfNecessary(); + } + + protected void Application_Error(object sender, EventArgs e) { + if (DataContextTransactionSimple != null) { + DataContextTransactionSimple.Rollback(); + DataContextTransactionSimple.Dispose(); + DataContextTransactionSimple = null; + } + } + + private static void CommitAndCloseDatabaseIfNecessary() { + var dataContext = DataContextSimple; + if (dataContext != null) { + dataContext.SaveChanges(); + if (DataContextTransactionSimple != null) { + DataContextTransactionSimple.Commit(); + DataContextTransactionSimple.Dispose(); + } + + dataContext.Dispose(); + DataContextSimple = null; + } + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.AuthenticationToken.cs b/projecttemplates/RelyingPartyLogic/Model.AuthenticationToken.cs new file mode 100644 index 0000000..e44fd83 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.AuthenticationToken.cs @@ -0,0 +1,21 @@ +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + + public partial class AuthenticationToken { + public bool IsInfoCard { + get { return this.ClaimedIdentifier.StartsWith(UriPrefixForInfoCard); } + } + + private static string UriPrefixForInfoCard { + get { return new Uri(Utilities.ApplicationRoot, "infocard/").AbsoluteUri; } + } + + public static string SynthesizeClaimedIdentifierFromInfoCard(string uniqueId) { + string synthesizedClaimedId = UriPrefixForInfoCard + Uri.EscapeDataString(uniqueId); + return synthesizedClaimedId; + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.Consumer.cs b/projecttemplates/RelyingPartyLogic/Model.Consumer.cs new file mode 100644 index 0000000..a09029a --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.Consumer.cs @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------- +// <copyright file="Model.Consumer.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Cryptography.X509Certificates; + using System.Web; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + + public partial class Consumer : IConsumerDescription { + public VerificationCodeFormat VerificationCodeFormat { + get { return (VerificationCodeFormat)this.VerificationCodeFormatAsInt; } + set { this.VerificationCodeFormatAsInt = (int)value; } + } + + public X509Certificate2 Certificate { + get { return this.X509CertificateAsBinary != null ? new X509Certificate2(this.X509CertificateAsBinary) : null; } + set { this.X509CertificateAsBinary = value != null ? value.RawData : null; } + } + + public Uri Callback { + get { return this.CallbackAsString != null ? new Uri(this.CallbackAsString) : null; } + set { this.CallbackAsString = value != null ? value.AbsoluteUri : null; } + } + + string IConsumerDescription.Secret { + get { return this.ConsumerSecret; } + } + + string IConsumerDescription.Key { + get { return this.ConsumerKey; } + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.Designer.cs b/projecttemplates/RelyingPartyLogic/Model.Designer.cs new file mode 100644 index 0000000..d19d305 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.Designer.cs @@ -0,0 +1,1168 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:2.0.50727.4927 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +[assembly: global::System.Data.Objects.DataClasses.EdmSchemaAttribute()] +[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "UserRole", "Role", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.Role), "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.User))] +[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "UserAuthenticationToken", "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(RelyingPartyLogic.User), "AuthenticationToken", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.AuthenticationToken))] +[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "Consumer", global::System.Data.Metadata.Edm.RelationshipMultiplicity.One, typeof(RelyingPartyLogic.Consumer), "IssuedTokens", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.IssuedToken))] +[assembly: global::System.Data.Objects.DataClasses.EdmRelationshipAttribute("DatabaseModel", "FK_IssuedToken_User", "User", global::System.Data.Metadata.Edm.RelationshipMultiplicity.ZeroOrOne, typeof(RelyingPartyLogic.User), "IssuedTokens", global::System.Data.Metadata.Edm.RelationshipMultiplicity.Many, typeof(RelyingPartyLogic.IssuedToken))] + +// Original file name: +// Generation date: 11/13/2009 4:45:45 PM +namespace RelyingPartyLogic +{ + + /// <summary> + /// There are no comments for DatabaseEntities in the schema. + /// </summary> + public partial class DatabaseEntities : global::System.Data.Objects.ObjectContext + { + /// <summary> + /// Initializes a new DatabaseEntities object using the connection string found in the 'DatabaseEntities' section of the application configuration file. + /// </summary> + public DatabaseEntities() : + base("name=DatabaseEntities", "DatabaseEntities") + { + this.OnContextCreated(); + } + /// <summary> + /// Initialize a new DatabaseEntities object. + /// </summary> + public DatabaseEntities(string connectionString) : + base(connectionString, "DatabaseEntities") + { + this.OnContextCreated(); + } + /// <summary> + /// Initialize a new DatabaseEntities object. + /// </summary> + public DatabaseEntities(global::System.Data.EntityClient.EntityConnection connection) : + base(connection, "DatabaseEntities") + { + this.OnContextCreated(); + } + partial void OnContextCreated(); + /// <summary> + /// There are no comments for Role in the schema. + /// </summary> + public global::System.Data.Objects.ObjectQuery<Role> Role + { + get + { + if ((this._Role == null)) + { + this._Role = base.CreateQuery<Role>("[Role]"); + } + return this._Role; + } + } + private global::System.Data.Objects.ObjectQuery<Role> _Role; + /// <summary> + /// There are no comments for User in the schema. + /// </summary> + public global::System.Data.Objects.ObjectQuery<User> User + { + get + { + if ((this._User == null)) + { + this._User = base.CreateQuery<User>("[User]"); + } + return this._User; + } + } + private global::System.Data.Objects.ObjectQuery<User> _User; + /// <summary> + /// There are no comments for AuthenticationToken in the schema. + /// </summary> + public global::System.Data.Objects.ObjectQuery<AuthenticationToken> AuthenticationToken + { + get + { + if ((this._AuthenticationToken == null)) + { + this._AuthenticationToken = base.CreateQuery<AuthenticationToken>("[AuthenticationToken]"); + } + return this._AuthenticationToken; + } + } + private global::System.Data.Objects.ObjectQuery<AuthenticationToken> _AuthenticationToken; + /// <summary> + /// There are no comments for Consumer in the schema. + /// </summary> + public global::System.Data.Objects.ObjectQuery<Consumer> Consumer + { + get + { + if ((this._Consumer == null)) + { + this._Consumer = base.CreateQuery<Consumer>("[Consumer]"); + } + return this._Consumer; + } + } + private global::System.Data.Objects.ObjectQuery<Consumer> _Consumer; + /// <summary> + /// There are no comments for IssuedToken in the schema. + /// </summary> + public global::System.Data.Objects.ObjectQuery<IssuedToken> IssuedToken + { + get + { + if ((this._IssuedToken == null)) + { + this._IssuedToken = base.CreateQuery<IssuedToken>("[IssuedToken]"); + } + return this._IssuedToken; + } + } + private global::System.Data.Objects.ObjectQuery<IssuedToken> _IssuedToken; + /// <summary> + /// There are no comments for Role in the schema. + /// </summary> + public void AddToRole(Role role) + { + base.AddObject("Role", role); + } + /// <summary> + /// There are no comments for User in the schema. + /// </summary> + public void AddToUser(User user) + { + base.AddObject("User", user); + } + /// <summary> + /// There are no comments for AuthenticationToken in the schema. + /// </summary> + public void AddToAuthenticationToken(AuthenticationToken authenticationToken) + { + base.AddObject("AuthenticationToken", authenticationToken); + } + /// <summary> + /// There are no comments for Consumer in the schema. + /// </summary> + public void AddToConsumer(Consumer consumer) + { + base.AddObject("Consumer", consumer); + } + /// <summary> + /// There are no comments for IssuedToken in the schema. + /// </summary> + public void AddToIssuedToken(IssuedToken issuedToken) + { + base.AddObject("IssuedToken", issuedToken); + } + } + /// <summary> + /// There are no comments for DatabaseModel.AuthenticationToken in the schema. + /// </summary> + /// <KeyProperties> + /// Id + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="AuthenticationToken")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class AuthenticationToken : global::System.Data.Objects.DataClasses.EntityObject + { + /// <summary> + /// Create a new AuthenticationToken object. + /// </summary> + /// <param name="id">Initial value of Id.</param> + /// <param name="claimedIdentifier">Initial value of ClaimedIdentifier.</param> + public static AuthenticationToken CreateAuthenticationToken(int id, string claimedIdentifier) + { + AuthenticationToken authenticationToken = new AuthenticationToken(); + authenticationToken.Id = id; + authenticationToken.ClaimedIdentifier = claimedIdentifier; + return authenticationToken; + } + /// <summary> + /// There are no comments for Property Id in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public int Id + { + get + { + return this._Id; + } + set + { + this.OnIdChanging(value); + this.ReportPropertyChanging("Id"); + this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("Id"); + this.OnIdChanged(); + } + } + private int _Id; + partial void OnIdChanging(int value); + partial void OnIdChanged(); + /// <summary> + /// There are no comments for Property ClaimedIdentifier in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string ClaimedIdentifier + { + get + { + return this._ClaimedIdentifier; + } + set + { + this.OnClaimedIdentifierChanging(value); + this.ReportPropertyChanging("ClaimedIdentifier"); + this._ClaimedIdentifier = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("ClaimedIdentifier"); + this.OnClaimedIdentifierChanged(); + } + } + private string _ClaimedIdentifier; + partial void OnClaimedIdentifierChanging(string value); + partial void OnClaimedIdentifierChanged(); + /// <summary> + /// There are no comments for Property FriendlyIdentifier in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string FriendlyIdentifier + { + get + { + return this._FriendlyIdentifier; + } + set + { + this.OnFriendlyIdentifierChanging(value); + this.ReportPropertyChanging("FriendlyIdentifier"); + this._FriendlyIdentifier = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("FriendlyIdentifier"); + this.OnFriendlyIdentifierChanged(); + } + } + private string _FriendlyIdentifier; + partial void OnFriendlyIdentifierChanging(string value); + partial void OnFriendlyIdentifierChanged(); + /// <summary> + /// There are no comments for User in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserAuthenticationToken", "User")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public User User + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User").Value; + } + set + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User").Value = value; + } + } + /// <summary> + /// There are no comments for User in the schema. + /// </summary> + [global::System.ComponentModel.BrowsableAttribute(false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityReference<User> UserReference + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<User>("DatabaseModel.UserAuthenticationToken", "User", value); + } + } + } + } + /// <summary> + /// There are no comments for DatabaseModel.Role in the schema. + /// </summary> + /// <KeyProperties> + /// Id + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Role")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class Role : global::System.Data.Objects.DataClasses.EntityObject + { + /// <summary> + /// Create a new Role object. + /// </summary> + /// <param name="id">Initial value of Id.</param> + /// <param name="name">Initial value of Name.</param> + public static Role CreateRole(int id, string name) + { + Role role = new Role(); + role.Id = id; + role.Name = name; + return role; + } + /// <summary> + /// There are no comments for Property Id in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public int Id + { + get + { + return this._Id; + } + private set + { + this.OnIdChanging(value); + this.ReportPropertyChanging("Id"); + this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("Id"); + this.OnIdChanged(); + } + } + private int _Id; + partial void OnIdChanging(int value); + partial void OnIdChanged(); + /// <summary> + /// There are no comments for Property Name in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string Name + { + get + { + return this._Name; + } + set + { + this.OnNameChanging(value); + this.ReportPropertyChanging("Name"); + this._Name = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("Name"); + this.OnNameChanged(); + } + } + private string _Name; + partial void OnNameChanging(string value); + partial void OnNameChanged(); + /// <summary> + /// There are no comments for Users in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserRole", "User")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityCollection<User> Users + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<User>("DatabaseModel.UserRole", "User"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<User>("DatabaseModel.UserRole", "User", value); + } + } + } + } + /// <summary> + /// There are no comments for DatabaseModel.User in the schema. + /// </summary> + /// <KeyProperties> + /// Id + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="User")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class User : global::System.Data.Objects.DataClasses.EntityObject + { + /// <summary> + /// Create a new User object. + /// </summary> + /// <param name="id">Initial value of Id.</param> + /// <param name="emailAddressVerified">Initial value of EmailAddressVerified.</param> + public static User CreateUser(int id, bool emailAddressVerified) + { + User user = new User(); + user.Id = id; + user.EmailAddressVerified = emailAddressVerified; + return user; + } + /// <summary> + /// There are no comments for Property Id in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public int Id + { + get + { + return this._Id; + } + private set + { + this.OnIdChanging(value); + this.ReportPropertyChanging("Id"); + this._Id = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("Id"); + this.OnIdChanged(); + } + } + private int _Id; + partial void OnIdChanging(int value); + partial void OnIdChanged(); + /// <summary> + /// There are no comments for Property FirstName in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string FirstName + { + get + { + return this._FirstName; + } + set + { + this.OnFirstNameChanging(value); + this.ReportPropertyChanging("FirstName"); + this._FirstName = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("FirstName"); + this.OnFirstNameChanged(); + } + } + private string _FirstName; + partial void OnFirstNameChanging(string value); + partial void OnFirstNameChanged(); + /// <summary> + /// There are no comments for Property LastName in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string LastName + { + get + { + return this._LastName; + } + set + { + this.OnLastNameChanging(value); + this.ReportPropertyChanging("LastName"); + this._LastName = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("LastName"); + this.OnLastNameChanged(); + } + } + private string _LastName; + partial void OnLastNameChanging(string value); + partial void OnLastNameChanged(); + /// <summary> + /// The email address claimed to be controlled by the user. Whether it is actually owned by the user is indicated by the EmailAddressVerified property. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string EmailAddress + { + get + { + return this._EmailAddress; + } + set + { + this.OnEmailAddressChanging(value); + this.ReportPropertyChanging("EmailAddress"); + this._EmailAddress = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("EmailAddress"); + this.OnEmailAddressChanged(); + } + } + private string _EmailAddress; + partial void OnEmailAddressChanging(string value); + partial void OnEmailAddressChanged(); + /// <summary> + /// A value indicating whether the email address has been verified as actually owned by this user. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public bool EmailAddressVerified + { + get + { + return this._EmailAddressVerified; + } + set + { + this.OnEmailAddressVerifiedChanging(value); + this.ReportPropertyChanging("EmailAddressVerified"); + this._EmailAddressVerified = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("EmailAddressVerified"); + this.OnEmailAddressVerifiedChanged(); + } + } + private bool _EmailAddressVerified; + partial void OnEmailAddressVerifiedChanging(bool value); + partial void OnEmailAddressVerifiedChanged(); + /// <summary> + /// There are no comments for Roles in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserRole", "Role")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityCollection<Role> Roles + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<Role>("DatabaseModel.UserRole", "Role"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<Role>("DatabaseModel.UserRole", "Role", value); + } + } + } + /// <summary> + /// There are no comments for AuthenticationTokens in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "UserAuthenticationToken", "AuthenticationToken")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityCollection<AuthenticationToken> AuthenticationTokens + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<AuthenticationToken>("DatabaseModel.UserAuthenticationToken", "AuthenticationToken"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<AuthenticationToken>("DatabaseModel.UserAuthenticationToken", "AuthenticationToken", value); + } + } + } + /// <summary> + /// There are no comments for IssuedToken in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User", "IssuedTokens")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityCollection<IssuedToken> IssuedToken + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_User", "IssuedTokens"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_User", "IssuedTokens", value); + } + } + } + } + /// <summary> + /// There are no comments for DatabaseModel.Consumer in the schema. + /// </summary> + /// <KeyProperties> + /// ConsumerId + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="Consumer")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class Consumer : global::System.Data.Objects.DataClasses.EntityObject + { + /// <summary> + /// Create a new Consumer object. + /// </summary> + /// <param name="consumerKey">Initial value of ConsumerKey.</param> + /// <param name="verificationCodeLength">Initial value of VerificationCodeLength.</param> + /// <param name="consumerId">Initial value of ConsumerId.</param> + public static Consumer CreateConsumer(string consumerKey, int verificationCodeLength, int consumerId) + { + Consumer consumer = new Consumer(); + consumer.ConsumerKey = consumerKey; + consumer.VerificationCodeLength = verificationCodeLength; + consumer.ConsumerId = consumerId; + return consumer; + } + /// <summary> + /// There are no comments for Property ConsumerKey in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string ConsumerKey + { + get + { + return this._ConsumerKey; + } + set + { + this.OnConsumerKeyChanging(value); + this.ReportPropertyChanging("ConsumerKey"); + this._ConsumerKey = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("ConsumerKey"); + this.OnConsumerKeyChanged(); + } + } + private string _ConsumerKey; + partial void OnConsumerKeyChanging(string value); + partial void OnConsumerKeyChanged(); + /// <summary> + /// There are no comments for Property ConsumerSecret in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string ConsumerSecret + { + get + { + return this._ConsumerSecret; + } + set + { + this.OnConsumerSecretChanging(value); + this.ReportPropertyChanging("ConsumerSecret"); + this._ConsumerSecret = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("ConsumerSecret"); + this.OnConsumerSecretChanged(); + } + } + private string _ConsumerSecret; + partial void OnConsumerSecretChanging(string value); + partial void OnConsumerSecretChanged(); + /// <summary> + /// There are no comments for Property X509CertificateAsBinary in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + private byte[] X509CertificateAsBinary + { + get + { + return global::System.Data.Objects.DataClasses.StructuralObject.GetValidValue(this._X509CertificateAsBinary); + } + set + { + this.OnX509CertificateAsBinaryChanging(value); + this.ReportPropertyChanging("X509CertificateAsBinary"); + this._X509CertificateAsBinary = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("X509CertificateAsBinary"); + this.OnX509CertificateAsBinaryChanged(); + } + } + private byte[] _X509CertificateAsBinary; + partial void OnX509CertificateAsBinaryChanging(byte[] value); + partial void OnX509CertificateAsBinaryChanged(); + /// <summary> + /// There are no comments for Property CallbackAsString in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string CallbackAsString + { + get + { + return this._CallbackAsString; + } + set + { + this.OnCallbackAsStringChanging(value); + this.ReportPropertyChanging("CallbackAsString"); + this._CallbackAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("CallbackAsString"); + this.OnCallbackAsStringChanged(); + } + } + private string _CallbackAsString; + partial void OnCallbackAsStringChanging(string value); + partial void OnCallbackAsStringChanged(); + /// <summary> + /// There are no comments for Property VerificationCodeFormatAsInt in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + private int VerificationCodeFormatAsInt + { + get + { + return this._VerificationCodeFormatAsInt; + } + set + { + this.OnVerificationCodeFormatAsIntChanging(value); + this.ReportPropertyChanging("VerificationCodeFormatAsInt"); + this._VerificationCodeFormatAsInt = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("VerificationCodeFormatAsInt"); + this.OnVerificationCodeFormatAsIntChanged(); + } + } + private int _VerificationCodeFormatAsInt; + partial void OnVerificationCodeFormatAsIntChanging(int value); + partial void OnVerificationCodeFormatAsIntChanged(); + /// <summary> + /// There are no comments for Property VerificationCodeLength in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public int VerificationCodeLength + { + get + { + return this._VerificationCodeLength; + } + set + { + this.OnVerificationCodeLengthChanging(value); + this.ReportPropertyChanging("VerificationCodeLength"); + this._VerificationCodeLength = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("VerificationCodeLength"); + this.OnVerificationCodeLengthChanged(); + } + } + private int _VerificationCodeLength; + partial void OnVerificationCodeLengthChanging(int value); + partial void OnVerificationCodeLengthChanged(); + /// <summary> + /// There are no comments for Property ConsumerId in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public int ConsumerId + { + get + { + return this._ConsumerId; + } + set + { + this.OnConsumerIdChanging(value); + this.ReportPropertyChanging("ConsumerId"); + this._ConsumerId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("ConsumerId"); + this.OnConsumerIdChanged(); + } + } + private int _ConsumerId; + partial void OnConsumerIdChanging(int value); + partial void OnConsumerIdChanged(); + /// <summary> + /// There are no comments for Property Name in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string Name + { + get + { + return this._Name; + } + set + { + this.OnNameChanging(value); + this.ReportPropertyChanging("Name"); + this._Name = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("Name"); + this.OnNameChanged(); + } + } + private string _Name; + partial void OnNameChanging(string value); + partial void OnNameChanged(); + /// <summary> + /// There are no comments for IssuedToken in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "IssuedTokens")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityCollection<IssuedToken> IssuedToken + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_Consumer", "IssuedTokens"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedCollection<IssuedToken>("DatabaseModel.FK_IssuedToken_Consumer", "IssuedTokens", value); + } + } + } + } + /// <summary> + /// There are no comments for DatabaseModel.IssuedToken in the schema. + /// </summary> + /// <KeyProperties> + /// TokenId + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="IssuedToken")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + [global::System.Runtime.Serialization.KnownTypeAttribute(typeof(global::RelyingPartyLogic.IssuedRequestToken))] + [global::System.Runtime.Serialization.KnownTypeAttribute(typeof(global::RelyingPartyLogic.IssuedAccessToken))] + public abstract partial class IssuedToken : global::System.Data.Objects.DataClasses.EntityObject + { + /// <summary> + /// There are no comments for Property TokenId in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public int TokenId + { + get + { + return this._TokenId; + } + set + { + this.OnTokenIdChanging(value); + this.ReportPropertyChanging("TokenId"); + this._TokenId = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("TokenId"); + this.OnTokenIdChanged(); + } + } + private int _TokenId; + partial void OnTokenIdChanging(int value); + partial void OnTokenIdChanged(); + /// <summary> + /// There are no comments for Property Token in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string Token + { + get + { + return this._Token; + } + set + { + this.OnTokenChanging(value); + this.ReportPropertyChanging("Token"); + this._Token = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("Token"); + this.OnTokenChanged(); + } + } + private string _Token; + partial void OnTokenChanging(string value); + partial void OnTokenChanged(); + /// <summary> + /// There are no comments for Property TokenSecret in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string TokenSecret + { + get + { + return this._TokenSecret; + } + set + { + this.OnTokenSecretChanging(value); + this.ReportPropertyChanging("TokenSecret"); + this._TokenSecret = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("TokenSecret"); + this.OnTokenSecretChanged(); + } + } + private string _TokenSecret; + partial void OnTokenSecretChanging(string value); + partial void OnTokenSecretChanged(); + /// <summary> + /// There are no comments for Property CreatedOn in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.DateTime CreatedOn + { + get + { + return this._CreatedOn; + } + set + { + this.OnCreatedOnChanging(value); + this.ReportPropertyChanging("CreatedOn"); + this._CreatedOn = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("CreatedOn"); + this.OnCreatedOnChanged(); + } + } + private global::System.DateTime _CreatedOn; + partial void OnCreatedOnChanging(global::System.DateTime value); + partial void OnCreatedOnChanged(); + /// <summary> + /// There are no comments for Property Scope in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string Scope + { + get + { + return this._Scope; + } + set + { + this.OnScopeChanging(value); + this.ReportPropertyChanging("Scope"); + this._Scope = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("Scope"); + this.OnScopeChanged(); + } + } + private string _Scope; + partial void OnScopeChanging(string value); + partial void OnScopeChanged(); + /// <summary> + /// There are no comments for Consumer in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_Consumer", "Consumer")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public Consumer Consumer + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer").Value; + } + set + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer").Value = value; + } + } + /// <summary> + /// There are no comments for Consumer in the schema. + /// </summary> + [global::System.ComponentModel.BrowsableAttribute(false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityReference<Consumer> ConsumerReference + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<Consumer>("DatabaseModel.FK_IssuedToken_Consumer", "Consumer", value); + } + } + } + /// <summary> + /// There are no comments for User in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmRelationshipNavigationPropertyAttribute("DatabaseModel", "FK_IssuedToken_User", "User")] + [global::System.Xml.Serialization.XmlIgnoreAttribute()] + [global::System.Xml.Serialization.SoapIgnoreAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public User User + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User").Value; + } + set + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User").Value = value; + } + } + /// <summary> + /// There are no comments for User in the schema. + /// </summary> + [global::System.ComponentModel.BrowsableAttribute(false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Data.Objects.DataClasses.EntityReference<User> UserReference + { + get + { + return ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.GetRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User"); + } + set + { + if ((value != null)) + { + ((global::System.Data.Objects.DataClasses.IEntityWithRelationships)(this)).RelationshipManager.InitializeRelatedReference<User>("DatabaseModel.FK_IssuedToken_User", "User", value); + } + } + } + } + /// <summary> + /// There are no comments for DatabaseModel.IssuedRequestToken in the schema. + /// </summary> + /// <KeyProperties> + /// TokenId + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="IssuedRequestToken")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class IssuedRequestToken : IssuedToken + { + /// <summary> + /// Create a new IssuedRequestToken object. + /// </summary> + /// <param name="tokenId">Initial value of TokenId.</param> + /// <param name="token">Initial value of Token.</param> + /// <param name="tokenSecret">Initial value of TokenSecret.</param> + /// <param name="createdOn">Initial value of CreatedOn.</param> + public static IssuedRequestToken CreateIssuedRequestToken(int tokenId, string token, string tokenSecret, global::System.DateTime createdOn) + { + IssuedRequestToken issuedRequestToken = new IssuedRequestToken(); + issuedRequestToken.TokenId = tokenId; + issuedRequestToken.Token = token; + issuedRequestToken.TokenSecret = tokenSecret; + issuedRequestToken.CreatedOn = createdOn; + return issuedRequestToken; + } + /// <summary> + /// There are no comments for Property ConsumerVersionAsString in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute(IsNullable=false)] + [global::System.Runtime.Serialization.DataMemberAttribute()] + private string ConsumerVersionAsString + { + get + { + return this._ConsumerVersionAsString; + } + set + { + this.OnConsumerVersionAsStringChanging(value); + this.ReportPropertyChanging("ConsumerVersionAsString"); + this._ConsumerVersionAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, false); + this.ReportPropertyChanged("ConsumerVersionAsString"); + this.OnConsumerVersionAsStringChanged(); + } + } + private string _ConsumerVersionAsString; + partial void OnConsumerVersionAsStringChanging(string value); + partial void OnConsumerVersionAsStringChanged(); + /// <summary> + /// There are no comments for Property VerificationCode in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public string VerificationCode + { + get + { + return this._VerificationCode; + } + set + { + this.OnVerificationCodeChanging(value); + this.ReportPropertyChanging("VerificationCode"); + this._VerificationCode = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("VerificationCode"); + this.OnVerificationCodeChanged(); + } + } + private string _VerificationCode; + partial void OnVerificationCodeChanging(string value); + partial void OnVerificationCodeChanged(); + /// <summary> + /// There are no comments for Property CallbackAsString in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + private string CallbackAsString + { + get + { + return this._CallbackAsString; + } + set + { + this.OnCallbackAsStringChanging(value); + this.ReportPropertyChanging("CallbackAsString"); + this._CallbackAsString = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value, true); + this.ReportPropertyChanged("CallbackAsString"); + this.OnCallbackAsStringChanged(); + } + } + private string _CallbackAsString; + partial void OnCallbackAsStringChanging(string value); + partial void OnCallbackAsStringChanged(); + } + /// <summary> + /// There are no comments for DatabaseModel.IssuedAccessToken in the schema. + /// </summary> + /// <KeyProperties> + /// TokenId + /// </KeyProperties> + [global::System.Data.Objects.DataClasses.EdmEntityTypeAttribute(NamespaceName="DatabaseModel", Name="IssuedAccessToken")] + [global::System.Runtime.Serialization.DataContractAttribute(IsReference=true)] + [global::System.Serializable()] + public partial class IssuedAccessToken : IssuedToken + { + /// <summary> + /// Create a new IssuedAccessToken object. + /// </summary> + /// <param name="tokenId">Initial value of TokenId.</param> + /// <param name="token">Initial value of Token.</param> + /// <param name="tokenSecret">Initial value of TokenSecret.</param> + /// <param name="createdOn">Initial value of CreatedOn.</param> + public static IssuedAccessToken CreateIssuedAccessToken(int tokenId, string token, string tokenSecret, global::System.DateTime createdOn) + { + IssuedAccessToken issuedAccessToken = new IssuedAccessToken(); + issuedAccessToken.TokenId = tokenId; + issuedAccessToken.Token = token; + issuedAccessToken.TokenSecret = tokenSecret; + issuedAccessToken.CreatedOn = createdOn; + return issuedAccessToken; + } + /// <summary> + /// There are no comments for Property ExpirationDate in the schema. + /// </summary> + [global::System.Data.Objects.DataClasses.EdmScalarPropertyAttribute()] + [global::System.Runtime.Serialization.DataMemberAttribute()] + public global::System.Nullable<global::System.DateTime> ExpirationDate + { + get + { + return this._ExpirationDate; + } + set + { + this.OnExpirationDateChanging(value); + this.ReportPropertyChanging("ExpirationDate"); + this._ExpirationDate = global::System.Data.Objects.DataClasses.StructuralObject.SetValidValue(value); + this.ReportPropertyChanged("ExpirationDate"); + this.OnExpirationDateChanged(); + } + } + private global::System.Nullable<global::System.DateTime> _ExpirationDate; + partial void OnExpirationDateChanging(global::System.Nullable<global::System.DateTime> value); + partial void OnExpirationDateChanged(); + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs b/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs new file mode 100644 index 0000000..fff27af --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.IssuedAccessToken.cs @@ -0,0 +1,58 @@ +//----------------------------------------------------------------------- +// <copyright file="Model.IssuedAccessToken.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public partial class IssuedAccessToken : IServiceProviderAccessToken { + /// <summary> + /// Gets the roles that the OAuth principal should belong to. + /// </summary> + /// <value> + /// The roles that the user belongs to, or a subset of these according to the rights + /// granted when the user authorized the request token. + /// </value> + string[] IServiceProviderAccessToken.Roles { + get { + List<string> roles = new List<string>(); + + // Include the roles the user who authorized this OAuth token has. + roles.AddRange(this.User.Roles.Select(r => r.Name)); + + // Always add an extra role to indicate this is an OAuth-authorized request. + // This allows us to deny access to account management pages to OAuth requests. + roles.Add("delegated"); + + return roles.ToArray(); + } + } + + /// <summary> + /// Gets the username of the principal that will be impersonated by this access token. + /// </summary> + /// <value> + /// The name of the user who authorized the OAuth request token originally. + /// </value> + string IServiceProviderAccessToken.Username { + get { + // We don't really have the concept of a single username, but we + // can use any of the authentication tokens instead since that + // is what the rest of the web site expects. + if (!this.UserReference.IsLoaded) { + this.UserReference.Load(); + } + if (!this.User.AuthenticationTokens.IsLoaded) { + this.User.AuthenticationTokens.Load(); + } + return this.User.AuthenticationTokens.First().ClaimedIdentifier; + } + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs b/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs new file mode 100644 index 0000000..c62f5c4 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.IssuedRequestToken.cs @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------- +// <copyright file="Model.IssuedRequestToken.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public partial class IssuedRequestToken : IServiceProviderRequestToken { + /// <summary> + /// Gets or sets the callback associated specifically with this token, if any. + /// </summary> + /// <value> + /// The callback URI; or <c>null</c> if no callback was specifically assigned to this token. + /// </value> + public Uri Callback { + get { return this.CallbackAsString != null ? new Uri(this.CallbackAsString) : null; } + set { this.CallbackAsString = value != null ? value.AbsoluteUri : null; } + } + + /// <summary> + /// Gets or sets the version of the Consumer that requested this token. + /// </summary> + /// <remarks> + /// This property is used to determine whether a <see cref="VerificationCode"/> must be + /// generated when the user authorizes the Consumer or not. + /// </remarks> + Version IServiceProviderRequestToken.ConsumerVersion { + get { return this.ConsumerVersionAsString != null ? new Version(this.ConsumerVersionAsString) : null; } + set { this.ConsumerVersionAsString = value != null ? value.ToString() : null; } + } + + /// <summary> + /// Gets the consumer key that requested this token. + /// </summary> + string IServiceProviderRequestToken.ConsumerKey { + get { return this.Consumer.ConsumerKey; } + } + + /// <summary> + /// Authorizes this request token to allow exchange for an access token. + /// </summary> + /// <remarks> + /// Call this method when the user has completed web-based authorization. + /// </remarks> + public void Authorize() { + this.User = Database.LoggedInUser; + Database.DataContext.SaveChanges(); + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.User.cs b/projecttemplates/RelyingPartyLogic/Model.User.cs new file mode 100644 index 0000000..16980e2 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.User.cs @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------- +// <copyright file="Model.User.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + + public partial class User { + partial void OnEmailAddressChanged() { + // Whenever the email address is changed, we must reset its verified status. + this.EmailAddressVerified = false; + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/Model.edmx b/projecttemplates/RelyingPartyLogic/Model.edmx new file mode 100644 index 0000000..f37aa6c --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Model.edmx @@ -0,0 +1,404 @@ +<?xml version="1.0" encoding="utf-8"?> +<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx"> + <!-- EF Runtime content --> + <edmx:Runtime> + <!-- SSDL content --> + <edmx:StorageModels> + <Schema Namespace="DatabaseModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2005" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl"> + <EntityContainer Name="DatabaseModelStoreContainer"> + <EntitySet Name="AuthenticationToken" EntityType="DatabaseModel.Store.AuthenticationToken" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="Consumer" EntityType="DatabaseModel.Store.Consumer" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="IssuedToken" EntityType="DatabaseModel.Store.IssuedToken" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="Role" EntityType="DatabaseModel.Store.Role" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="User" EntityType="DatabaseModel.Store.User" store:Type="Tables" Schema="dbo" /> + <EntitySet Name="UserRole" EntityType="DatabaseModel.Store.UserRole" store:Type="Tables" Schema="dbo" /> + <AssociationSet Name="FK_AuthenticationToken_User" Association="DatabaseModel.Store.FK_AuthenticationToken_User"> + <End Role="User" EntitySet="User" /> + <End Role="AuthenticationToken" EntitySet="AuthenticationToken" /> + </AssociationSet> + <AssociationSet Name="FK_IssuedToken_Consumer" Association="DatabaseModel.Store.FK_IssuedToken_Consumer"> + <End Role="Consumer" EntitySet="Consumer" /> + <End Role="IssuedToken" EntitySet="IssuedToken" /> + </AssociationSet> + <AssociationSet Name="FK_IssuedToken_User" Association="DatabaseModel.Store.FK_IssuedToken_User"> + <End Role="User" EntitySet="User" /> + <End Role="IssuedToken" EntitySet="IssuedToken" /> + </AssociationSet> + <AssociationSet Name="FK_UserRole_Role" Association="DatabaseModel.Store.FK_UserRole_Role"> + <End Role="Role" EntitySet="Role" /> + <End Role="UserRole" EntitySet="UserRole" /> + </AssociationSet> + <AssociationSet Name="FK_UserRole_User" Association="DatabaseModel.Store.FK_UserRole_User"> + <End Role="User" EntitySet="User" /> + <End Role="UserRole" EntitySet="UserRole" /> + </AssociationSet> + </EntityContainer> + <EntityType Name="AuthenticationToken"> + <Key> + <PropertyRef Name="Id" /> + </Key> + <Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> + <Property Name="UserId" Type="int" Nullable="false" /> + <Property Name="OpenIdClaimedIdentifier" Type="nvarchar" Nullable="false" MaxLength="250" /> + <Property Name="OpenIdFriendlyIdentifier" Type="nvarchar" MaxLength="250" /> + </EntityType> + <EntityType Name="Consumer"> + <Key> + <PropertyRef Name="ConsumerId" /> + </Key> + <Property Name="ConsumerId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> + <Property Name="ConsumerKey" Type="nvarchar" Nullable="false" MaxLength="255" /> + <Property Name="ConsumerSecret" Type="nvarchar" MaxLength="255" /> + <Property Name="X509Certificate" Type="image" /> + <Property Name="Callback" Type="nvarchar" MaxLength="2048" /> + <Property Name="VerificationCodeFormat" Type="int" Nullable="false" /> + <Property Name="VerificationCodeLength" Type="int" Nullable="false" /> + <Property Name="Name" Type="nvarchar" MaxLength="50" /> + </EntityType> + <EntityType Name="IssuedToken"> + <Key> + <PropertyRef Name="TokenId" /> + </Key> + <Property Name="TokenId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> + <Property Name="ConsumerId" Type="int" Nullable="false" /> + <Property Name="UserId" Type="int" /> + <Property Name="Token" Type="nvarchar" Nullable="false" MaxLength="255" /> + <Property Name="TokenSecret" Type="nvarchar" Nullable="false" MaxLength="255" /> + <Property Name="CreatedOn" Type="datetime" Nullable="false" /> + <Property Name="Callback" Type="nvarchar" MaxLength="2048" /> + <Property Name="VerificationCode" Type="nvarchar" MaxLength="255" /> + <Property Name="ConsumerVersion" Type="varchar" MaxLength="10" /> + <Property Name="ExpirationDate" Type="datetime" /> + <Property Name="IsAccessToken" Type="bit" Nullable="false" /> + <Property Name="Scope" Type="nvarchar" MaxLength="255" /> + </EntityType> + <EntityType Name="Role"> + <Key> + <PropertyRef Name="Id" /> + </Key> + <Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> + <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" /> + </EntityType> + <EntityType Name="User"> + <Key> + <PropertyRef Name="Id" /> + </Key> + <Property Name="Id" Type="int" Nullable="false" StoreGeneratedPattern="Identity" /> + <Property Name="FirstName" Type="nvarchar" MaxLength="50" /> + <Property Name="LastName" Type="nvarchar" MaxLength="50" /> + <Property Name="EmailAddress" Type="nvarchar" MaxLength="100" /> + <Property Name="EmailAddressVerified" Type="bit" Nullable="false" /> + </EntityType> + <EntityType Name="UserRole"> + <Key> + <PropertyRef Name="UserId" /> + <PropertyRef Name="RoleId" /> + </Key> + <Property Name="UserId" Type="int" Nullable="false" /> + <Property Name="RoleId" Type="int" Nullable="false" /> + </EntityType> + <Association Name="FK_AuthenticationToken_User"> + <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="1"> + <OnDelete Action="Cascade" /> + </End> + <End Role="AuthenticationToken" Type="DatabaseModel.Store.AuthenticationToken" Multiplicity="*" /> + <ReferentialConstraint> + <Principal Role="User"> + <PropertyRef Name="Id" /> + </Principal> + <Dependent Role="AuthenticationToken"> + <PropertyRef Name="UserId" /> + </Dependent> + </ReferentialConstraint> + </Association> + <Association Name="FK_IssuedToken_Consumer"> + <End Role="Consumer" Type="DatabaseModel.Store.Consumer" Multiplicity="1"> + <OnDelete Action="Cascade" /> + </End> + <End Role="IssuedToken" Type="DatabaseModel.Store.IssuedToken" Multiplicity="*" /> + <ReferentialConstraint> + <Principal Role="Consumer"> + <PropertyRef Name="ConsumerId" /> + </Principal> + <Dependent Role="IssuedToken"> + <PropertyRef Name="ConsumerId" /> + </Dependent> + </ReferentialConstraint> + </Association> + <Association Name="FK_IssuedToken_User"> + <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="0..1"> + <OnDelete Action="Cascade" /> + </End> + <End Role="IssuedToken" Type="DatabaseModel.Store.IssuedToken" Multiplicity="*" /> + <ReferentialConstraint> + <Principal Role="User"> + <PropertyRef Name="Id" /> + </Principal> + <Dependent Role="IssuedToken"> + <PropertyRef Name="UserId" /> + </Dependent> + </ReferentialConstraint> + </Association> + <Association Name="FK_UserRole_Role"> + <End Role="Role" Type="DatabaseModel.Store.Role" Multiplicity="1"> + <OnDelete Action="Cascade" /> + </End> + <End Role="UserRole" Type="DatabaseModel.Store.UserRole" Multiplicity="*" /> + <ReferentialConstraint> + <Principal Role="Role"> + <PropertyRef Name="Id" /> + </Principal> + <Dependent Role="UserRole"> + <PropertyRef Name="RoleId" /> + </Dependent> + </ReferentialConstraint> + </Association> + <Association Name="FK_UserRole_User"> + <End Role="User" Type="DatabaseModel.Store.User" Multiplicity="1"> + <OnDelete Action="Cascade" /> + </End> + <End Role="UserRole" Type="DatabaseModel.Store.UserRole" Multiplicity="*" /> + <ReferentialConstraint> + <Principal Role="User"> + <PropertyRef Name="Id" /> + </Principal> + <Dependent Role="UserRole"> + <PropertyRef Name="UserId" /> + </Dependent> + </ReferentialConstraint> + </Association> + </Schema></edmx:StorageModels> + <!-- CSDL content --> + <edmx:ConceptualModels> + <Schema Namespace="DatabaseModel" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm"> + <EntityContainer Name="DatabaseEntities"> + <EntitySet Name="Role" EntityType="DatabaseModel.Role" /> + <EntitySet Name="User" EntityType="DatabaseModel.User" /> + <AssociationSet Name="UserRole" Association="DatabaseModel.UserRole"> + <End Role="Role" EntitySet="Role" /> + <End Role="User" EntitySet="User" /> + </AssociationSet> + <EntitySet Name="AuthenticationToken" EntityType="DatabaseModel.AuthenticationToken" /> + <AssociationSet Name="UserAuthenticationToken" Association="DatabaseModel.UserAuthenticationToken"> + <End Role="User" EntitySet="User" /> + <End Role="AuthenticationToken" EntitySet="AuthenticationToken" /></AssociationSet> + <EntitySet Name="Consumer" EntityType="DatabaseModel.Consumer" /> + <EntitySet Name="IssuedToken" EntityType="DatabaseModel.IssuedToken" /> + <AssociationSet Name="FK_IssuedToken_Consumer" Association="DatabaseModel.FK_IssuedToken_Consumer"> + <End Role="Consumer" EntitySet="Consumer" /> + <End Role="IssuedTokens" EntitySet="IssuedToken" /></AssociationSet> + <AssociationSet Name="FK_IssuedToken_User" Association="DatabaseModel.FK_IssuedToken_User"> + <End Role="User" EntitySet="User" /> + <End Role="IssuedTokens" EntitySet="IssuedToken" /></AssociationSet> + </EntityContainer> + <EntityType Name="AuthenticationToken" Abstract="false"> + <Key> + <PropertyRef Name="Id" /></Key> + <Property Name="Id" Type="Int32" Nullable="false" a:SetterAccess="Public" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> + <NavigationProperty Name="User" Relationship="DatabaseModel.UserAuthenticationToken" FromRole="AuthenticationToken" ToRole="User" /> + <Property Name="ClaimedIdentifier" Type="String" Nullable="false" /> + <Property Name="FriendlyIdentifier" Type="String" Nullable="true" /></EntityType> + <EntityType Name="Role"> + <Key> + <PropertyRef Name="Id" /> + </Key> + <Property Name="Id" Type="Int32" Nullable="false" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> + <Property Name="Name" Type="String" Nullable="false" MaxLength="50" Unicode="true" FixedLength="false" /> + <NavigationProperty Name="Users" Relationship="DatabaseModel.UserRole" FromRole="Role" ToRole="User" /> + </EntityType> + <EntityType Name="User"> + <Key> + <PropertyRef Name="Id" /> + </Key> + <Property Name="Id" Type="Int32" Nullable="false" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" /> + <Property Name="FirstName" Type="String" MaxLength="50" Unicode="true" FixedLength="false" /> + <Property Name="LastName" Type="String" MaxLength="50" Unicode="true" FixedLength="false" /> + <Property Name="EmailAddress" Type="String" MaxLength="100" Unicode="true" FixedLength="false" > + <Documentation> + <Summary>The email address claimed to be controlled by the user. Whether it is actually owned by the user is indicated by the EmailAddressVerified property.</Summary></Documentation></Property> + <NavigationProperty Name="Roles" Relationship="DatabaseModel.UserRole" FromRole="User" ToRole="Role" /> + <NavigationProperty Name="AuthenticationTokens" Relationship="DatabaseModel.UserAuthenticationToken" FromRole="User" ToRole="AuthenticationToken" /> + <Property Name="EmailAddressVerified" Type="Boolean" Nullable="false" > + <Documentation> + <Summary>A value indicating whether the email address has been verified as actually owned by this user.</Summary></Documentation></Property> + <NavigationProperty Name="IssuedToken" Relationship="DatabaseModel.FK_IssuedToken_User" FromRole="User" ToRole="IssuedTokens" /></EntityType> + <Association Name="UserRole"> + <End Role="Role" Type="DatabaseModel.Role" Multiplicity="*" /> + <End Role="User" Type="DatabaseModel.User" Multiplicity="*" /> + </Association> + <Association Name="UserAuthenticationToken"> + <End Type="DatabaseModel.User" Role="User" Multiplicity="1" /> + <End Type="DatabaseModel.AuthenticationToken" Role="AuthenticationToken" Multiplicity="*" /></Association> + <EntityType Name="Consumer"> + <Key> + <PropertyRef Name="ConsumerId" /></Key> + <Property Name="ConsumerKey" Type="String" Nullable="false" /> + <Property Name="ConsumerSecret" Type="String" Nullable="true" /> + <Property Name="X509CertificateAsBinary" Type="Binary" Nullable="true" a:SetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:GetterAccess="Private" /> + <Property Name="CallbackAsString" Type="String" Nullable="true" /> + <Property Name="VerificationCodeFormatAsInt" Type="Int32" Nullable="false" a:GetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:SetterAccess="Private" /> + <Property Name="VerificationCodeLength" Type="Int32" Nullable="false" /> + <Property Name="ConsumerId" Type="Int32" Nullable="false" /> + <NavigationProperty Name="IssuedToken" Relationship="DatabaseModel.FK_IssuedToken_Consumer" FromRole="Consumer" ToRole="IssuedTokens" /> + <Property Name="Name" Type="String" Nullable="true" /></EntityType> + <EntityType Name="IssuedToken" Abstract="true"> + <Key> + <PropertyRef Name="TokenId" /></Key> + <Property Name="TokenId" Type="Int32" Nullable="false" /> + <Property Name="Token" Type="String" Nullable="false" /> + <Property Name="TokenSecret" Type="String" Nullable="false" /> + <Property Name="CreatedOn" Type="DateTime" Nullable="false" /> + <NavigationProperty Name="Consumer" Relationship="DatabaseModel.FK_IssuedToken_Consumer" FromRole="IssuedTokens" ToRole="Consumer" /> + <NavigationProperty Name="User" Relationship="DatabaseModel.FK_IssuedToken_User" FromRole="IssuedTokens" ToRole="User" /> + <Property Name="Scope" Type="String" Nullable="true" /></EntityType> + <Association Name="FK_IssuedToken_Consumer"> + <End Type="DatabaseModel.Consumer" Role="Consumer" Multiplicity="1" /> + <End Type="DatabaseModel.IssuedToken" Role="IssuedTokens" Multiplicity="*" /></Association> + <Association Name="FK_IssuedToken_User"> + <End Type="DatabaseModel.User" Role="User" Multiplicity="0..1" /> + <End Type="DatabaseModel.IssuedToken" Role="IssuedTokens" Multiplicity="*" /></Association> + <EntityType Name="IssuedRequestToken" BaseType="DatabaseModel.IssuedToken"> + <Property Name="ConsumerVersionAsString" Type="String" Nullable="false" a:GetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:SetterAccess="Private" /> + <Property Name="VerificationCode" Type="String" Nullable="true" /> + <Property Name="CallbackAsString" Type="String" Nullable="true" a:GetterAccess="Private" xmlns:a="http://schemas.microsoft.com/ado/2006/04/codegeneration" a:SetterAccess="Private" /></EntityType> + <EntityType Name="IssuedAccessToken" BaseType="DatabaseModel.IssuedToken"> + <Property Name="ExpirationDate" Type="DateTime" Nullable="true" /></EntityType></Schema> + </edmx:ConceptualModels> + <!-- C-S mapping content --> + <edmx:Mappings> + <Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS"> + <EntityContainerMapping StorageEntityContainer="DatabaseModelStoreContainer" CdmEntityContainer="DatabaseEntities"> + <EntitySetMapping Name="Role"> + <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.Role)"> + <MappingFragment StoreEntitySet="Role"> + <ScalarProperty Name="Id" ColumnName="Id" /> + <ScalarProperty Name="Name" ColumnName="Name" /> + </MappingFragment> + </EntityTypeMapping> + </EntitySetMapping> + <EntitySetMapping Name="User"> + <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.User)"> + <MappingFragment StoreEntitySet="User"> + <ScalarProperty Name="EmailAddressVerified" ColumnName="EmailAddressVerified" /> + <ScalarProperty Name="Id" ColumnName="Id" /> + <ScalarProperty Name="FirstName" ColumnName="FirstName" /> + <ScalarProperty Name="LastName" ColumnName="LastName" /> + <ScalarProperty Name="EmailAddress" ColumnName="EmailAddress" /> + </MappingFragment> + </EntityTypeMapping> + </EntitySetMapping> + <AssociationSetMapping Name="UserRole" TypeName="DatabaseModel.UserRole" StoreEntitySet="UserRole"> + <EndProperty Name="Role"> + <ScalarProperty Name="Id" ColumnName="RoleId" /> + </EndProperty> + <EndProperty Name="User"> + <ScalarProperty Name="Id" ColumnName="UserId" /> + </EndProperty> + </AssociationSetMapping> + <EntitySetMapping Name="AuthenticationToken"><EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.AuthenticationToken)"> + <MappingFragment StoreEntitySet="AuthenticationToken"> + <ScalarProperty Name="FriendlyIdentifier" ColumnName="OpenIdFriendlyIdentifier" /> + <ScalarProperty Name="ClaimedIdentifier" ColumnName="OpenIdClaimedIdentifier" /> + <ScalarProperty Name="Id" ColumnName="Id" /> + </MappingFragment> + </EntityTypeMapping> + </EntitySetMapping> + <AssociationSetMapping Name="UserAuthenticationToken" TypeName="DatabaseModel.UserAuthenticationToken" StoreEntitySet="AuthenticationToken"> + <EndProperty Name="AuthenticationToken"> + <ScalarProperty Name="Id" ColumnName="Id" /></EndProperty> + <EndProperty Name="User"> + <ScalarProperty Name="Id" ColumnName="UserId" /></EndProperty></AssociationSetMapping> + <EntitySetMapping Name="Consumer"> + <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.Consumer)"> + <MappingFragment StoreEntitySet="Consumer"> + <ScalarProperty Name="Name" ColumnName="Name" /> + <ScalarProperty Name="ConsumerId" ColumnName="ConsumerId" /> + <ScalarProperty Name="VerificationCodeLength" ColumnName="VerificationCodeLength" /> + <ScalarProperty Name="VerificationCodeFormatAsInt" ColumnName="VerificationCodeFormat" /> + <ScalarProperty Name="CallbackAsString" ColumnName="Callback" /> + <ScalarProperty Name="X509CertificateAsBinary" ColumnName="X509Certificate" /> + <ScalarProperty Name="ConsumerSecret" ColumnName="ConsumerSecret" /> + <ScalarProperty Name="ConsumerKey" ColumnName="ConsumerKey" /></MappingFragment></EntityTypeMapping></EntitySetMapping> + <EntitySetMapping Name="IssuedToken"> + <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedToken)"> + <MappingFragment StoreEntitySet="IssuedToken"> + <ScalarProperty Name="Scope" ColumnName="Scope" /> + <ScalarProperty Name="CreatedOn" ColumnName="CreatedOn" /> + <ScalarProperty Name="TokenSecret" ColumnName="TokenSecret" /> + <ScalarProperty Name="Token" ColumnName="Token" /> + <ScalarProperty Name="TokenId" ColumnName="TokenId" /></MappingFragment></EntityTypeMapping> + <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedRequestToken)"> + <MappingFragment StoreEntitySet="IssuedToken" > + <ScalarProperty Name="CallbackAsString" ColumnName="Callback" /> + <ScalarProperty Name="ConsumerVersionAsString" ColumnName="ConsumerVersion" /> + <ScalarProperty Name="VerificationCode" ColumnName="VerificationCode" /> + <ScalarProperty Name="TokenId" ColumnName="TokenId" /> + <Condition ColumnName="IsAccessToken" Value="0" /></MappingFragment></EntityTypeMapping> + <EntityTypeMapping TypeName="IsTypeOf(DatabaseModel.IssuedAccessToken)"> + <MappingFragment StoreEntitySet="IssuedToken" > + <ScalarProperty Name="ExpirationDate" ColumnName="ExpirationDate" /> + <ScalarProperty Name="TokenId" ColumnName="TokenId" /> + <Condition ColumnName="IsAccessToken" Value="1" /></MappingFragment></EntityTypeMapping></EntitySetMapping> + <AssociationSetMapping Name="FK_IssuedToken_Consumer" TypeName="DatabaseModel.FK_IssuedToken_Consumer" StoreEntitySet="IssuedToken"> + <EndProperty Name="IssuedTokens"> + <ScalarProperty Name="TokenId" ColumnName="TokenId" /></EndProperty> + <EndProperty Name="Consumer"> + <ScalarProperty Name="ConsumerId" ColumnName="ConsumerId" /></EndProperty></AssociationSetMapping> + <AssociationSetMapping Name="FK_IssuedToken_User" TypeName="DatabaseModel.FK_IssuedToken_User" StoreEntitySet="IssuedToken"> + <EndProperty Name="IssuedTokens"> + <ScalarProperty Name="TokenId" ColumnName="TokenId" /></EndProperty> + <EndProperty Name="User"> + <ScalarProperty Name="Id" ColumnName="UserId" /></EndProperty> + <Condition ColumnName="UserId" IsNull="false" /></AssociationSetMapping></EntityContainerMapping> + </Mapping> + </edmx:Mappings> + </edmx:Runtime> + <!-- EF Designer content (DO NOT EDIT MANUALLY BELOW HERE) --> + <edmx:Designer xmlns="http://schemas.microsoft.com/ado/2007/06/edmx"> + <edmx:Connection> + <DesignerInfoPropertySet> + <DesignerProperty Name="MetadataArtifactProcessing" Value="EmbedInOutputAssembly" /> + </DesignerInfoPropertySet> + </edmx:Connection> + <edmx:Options> + <DesignerInfoPropertySet> + <DesignerProperty Name="ValidateOnBuild" Value="true" /> + </DesignerInfoPropertySet> + </edmx:Options> + <!-- Diagram content (shape and connector positions) --> + <edmx:Diagrams> + <Diagram Name="Model"> + <EntityTypeShape EntityType="DatabaseModel.AuthenticationToken" Width="1.875" PointX="5.25" PointY="1.125" Height="1.4033821614583335" IsExpanded="true" /> + <EntityTypeShape EntityType="DatabaseModel.Role" Width="1.5" PointX="0.75" PointY="1.25" Height="1.5956835937500002" IsExpanded="true" /> + <EntityTypeShape EntityType="DatabaseModel.User" Width="1.75" PointX="2.875" PointY="0.875" Height="2.3648893229166661" IsExpanded="true" /> + <AssociationConnector Association="DatabaseModel.UserRole" ManuallyRouted="false"> + <ConnectorPoint PointX="2.25" PointY="2.0478417968750002" /> + <ConnectorPoint PointX="2.875" PointY="2.0478417968750002" /></AssociationConnector> + <InheritanceConnector EntityType="DatabaseModel.AuthenticationToken"> + <ConnectorPoint PointX="6.5625" PointY="3.375" /> + <ConnectorPoint PointX="6.5625" PointY="2.9129850260416665" /></InheritanceConnector> + <AssociationConnector Association="DatabaseModel.UserAuthenticationToken"> + <ConnectorPoint PointX="4.625" PointY="2.0189925130208337" /> + <ConnectorPoint PointX="5.25" PointY="2.0189925130208337" /></AssociationConnector> + <EntityTypeShape EntityType="DatabaseModel.Consumer" Width="2.125" PointX="0.5" PointY="3.625" Height="2.1725878906249996" /> + <EntityTypeShape EntityType="DatabaseModel.IssuedToken" Width="2" PointX="4.5" PointY="3.625" Height="2.1725878906249996" /> + <AssociationConnector Association="DatabaseModel.FK_IssuedToken_Consumer" ManuallyRouted="false" > + <ConnectorPoint PointX="2.625" PointY="5.359375" /> + <ConnectorPoint PointX="4.5" PointY="5.359375" /> + </AssociationConnector> + <AssociationConnector Association="DatabaseModel.FK_IssuedToken_User" > + <ConnectorPoint PointX="3.6874995" PointY="3.4321907552083331" /> + <ConnectorPoint PointX="3.6874995" PointY="4.005208333333333" /> + <ConnectorPoint PointX="4.5" PointY="4.005208333333333" /> + </AssociationConnector> + <EntityTypeShape EntityType="DatabaseModel.IssuedRequestToken" Width="2" PointX="4.25" PointY="6.25" Height="1.5956835937499996" /> + <EntityTypeShape EntityType="DatabaseModel.IssuedAccessToken" Width="1.625" PointX="6.5" PointY="6.25" Height="1.2110807291666657" /> + <InheritanceConnector EntityType="DatabaseModel.IssuedRequestToken"> + <ConnectorPoint PointX="5.375" PointY="5.797587890625" /> + <ConnectorPoint PointX="5.375" PointY="6.25" /></InheritanceConnector> + <InheritanceConnector EntityType="DatabaseModel.IssuedAccessToken"> + <ConnectorPoint PointX="6.5" PointY="4.7112939453125" /> + <ConnectorPoint PointX="7.34375" PointY="4.7112939453125" /> + <ConnectorPoint PointX="7.34375" PointY="6.25" /></InheritanceConnector></Diagram></edmx:Diagrams> + </edmx:Designer> +</edmx:Edmx>
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs new file mode 100644 index 0000000..e47e4ee --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthenticationModule.cs @@ -0,0 +1,78 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthAuthenticationModule.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Principal; + using System.Web; + using System.Web.Security; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + public class OAuthAuthenticationModule : IHttpModule { + private HttpApplication application; + + #region IHttpModule Members + + /// <summary> + /// Initializes a module and prepares it to handle requests. + /// </summary> + /// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application</param> + public void Init(HttpApplication context) { + this.application = context; + this.application.AuthenticateRequest += this.context_AuthenticateRequest; + + // Register an event that allows us to override roles for OAuth requests. + var roleManager = (RoleManagerModule)this.application.Modules["RoleManager"]; + roleManager.GetRoles += this.roleManager_GetRoles; + } + + /// <summary> + /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>. + /// </summary> + public void Dispose() { + } + + /// <summary> + /// Handles the AuthenticateRequest event of the HttpApplication. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param> + private void context_AuthenticateRequest(object sender, EventArgs e) { + // Don't read OAuth messages directed at the OAuth controller or else we'll fail nonce checks. + if (this.IsOAuthControllerRequest()) { + return; + } + + IDirectedProtocolMessage incomingMessage = OAuthServiceProvider.ServiceProvider.ReadRequest(new HttpRequestInfo(this.application.Context.Request)); + var authorization = incomingMessage as AccessProtectedResourceRequest; + if (authorization != null) { + this.application.Context.User = OAuthServiceProvider.ServiceProvider.CreatePrincipal(authorization); + } + } + + #endregion + + private bool IsOAuthControllerRequest() { + return string.Equals(this.application.Context.Request.Url.AbsolutePath, "/OAuth.ashx", StringComparison.OrdinalIgnoreCase); + } + + /// <summary> + /// Handles the GetRoles event of the roleManager control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="System.Web.Security.RoleManagerEventArgs"/> instance containing the event data.</param> + private void roleManager_GetRoles(object sender, RoleManagerEventArgs e) { + if (this.application.User is OAuthPrincipal) { + e.RolesPopulated = true; + } + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs new file mode 100644 index 0000000..752e2eb --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthAuthorizationManager.cs @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthAuthorizationManager.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.IdentityModel.Policy; + using System.Linq; + using System.Security.Principal; + using System.ServiceModel; + using System.ServiceModel.Channels; + using System.ServiceModel.Security; + using DotNetOpenAuth; + using DotNetOpenAuth.OAuth; + + /// <summary> + /// A WCF extension to authenticate incoming messages using OAuth. + /// </summary> + public class OAuthAuthorizationManager : ServiceAuthorizationManager { + public OAuthAuthorizationManager() { + } + + protected override bool CheckAccessCore(OperationContext operationContext) { + if (!base.CheckAccessCore(operationContext)) { + return false; + } + + HttpRequestMessageProperty httpDetails = operationContext.RequestContext.RequestMessage.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; + Uri requestUri = operationContext.RequestContext.RequestMessage.Properties["OriginalHttpRequestUri"] as Uri; + ServiceProvider sp = OAuthServiceProvider.ServiceProvider; + var auth = sp.ReadProtectedResourceAuthorization(httpDetails, requestUri); + if (auth != null) { + var accessToken = Database.DataContext.IssuedToken.OfType<IssuedAccessToken>().First(token => token.Token == auth.AccessToken); + + var principal = sp.CreatePrincipal(auth); + var policy = new OAuthPrincipalAuthorizationPolicy(principal); + var policies = new List<IAuthorizationPolicy> { + policy, + }; + + var securityContext = new ServiceSecurityContext(policies.AsReadOnly()); + if (operationContext.IncomingMessageProperties.Security != null) { + operationContext.IncomingMessageProperties.Security.ServiceSecurityContext = securityContext; + } else { + operationContext.IncomingMessageProperties.Security = new SecurityMessageProperty { + ServiceSecurityContext = securityContext, + }; + } + + securityContext.AuthorizationContext.Properties["Identities"] = new List<IIdentity> { + principal.Identity, + }; + + // Only allow this method call if the access token scope permits it. + string[] scopes = accessToken.Scope.Split('|'); + if (scopes.Contains(operationContext.IncomingMessageHeaders.Action)) { + return true; + } + } + + return false; + } + } +}
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs new file mode 100644 index 0000000..64e6be8 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthConsumerTokenManager.cs @@ -0,0 +1,48 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthConsumerTokenManager.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class OAuthConsumerTokenManager : OAuthTokenManager, IConsumerTokenManager { + /// <summary> + /// Initializes a new instance of the <see cref="OAuthConsumerTokenManager"/> class. + /// </summary> + /// <param name="consumerKey">The consumer key.</param> + /// <param name="consumerSecret">The consumer secret.</param> + public OAuthConsumerTokenManager(string consumerKey, string consumerSecret) { + if (String.IsNullOrEmpty(consumerKey)) { + throw new ArgumentNullException("consumerKey"); + } + if (consumerSecret == null) { + throw new ArgumentNullException("consumerSecret"); + } + + this.ConsumerKey = consumerKey; + this.ConsumerSecret = consumerSecret; + } + + #region IConsumerTokenManager Members + + /// <summary> + /// Gets the consumer key. + /// </summary> + /// <value>The consumer key.</value> + public string ConsumerKey { get; private set; } + + /// <summary> + /// Gets the consumer secret. + /// </summary> + /// <value>The consumer secret.</value> + public string ConsumerSecret { get; private set; } + + #endregion + } +} diff --git a/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs b/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs new file mode 100644 index 0000000..ddd0b3f --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthPrincipalAuthorizationPolicy.cs @@ -0,0 +1,53 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthPrincipalAuthorizationPolicy.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.IdentityModel.Claims; + using System.IdentityModel.Policy; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class OAuthPrincipalAuthorizationPolicy : IAuthorizationPolicy { + private readonly Guid uniqueId = Guid.NewGuid(); + private readonly OAuthPrincipal principal; + + /// <summary> + /// Initializes a new instance of the <see cref="OAuthPrincipalAuthorizationPolicy"/> class. + /// </summary> + /// <param name="principal">The principal.</param> + public OAuthPrincipalAuthorizationPolicy(OAuthPrincipal principal) { + this.principal = principal; + } + + #region IAuthorizationComponent Members + + /// <summary> + /// Gets a unique ID for this instance. + /// </summary> + public string Id { + get { return this.uniqueId.ToString(); } + } + + #endregion + + #region IAuthorizationPolicy Members + + public ClaimSet Issuer { + get { return ClaimSet.System; } + } + + public bool Evaluate(EvaluationContext evaluationContext, ref object state) { + evaluationContext.AddClaimSet(this, new DefaultClaimSet(Claim.CreateNameClaim(this.principal.Identity.Name))); + evaluationContext.Properties["Principal"] = this.principal; + return true; + } + + #endregion + } +}
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs b/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs new file mode 100644 index 0000000..8d582ab --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthServiceProvider.cs @@ -0,0 +1,120 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthServiceProvider.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.Messaging; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + public class OAuthServiceProvider { + private const string PendingAuthorizationRequestSessionKey = "PendingAuthorizationRequest"; + + /// <summary> + /// The shared service description for this web site. + /// </summary> + private static ServiceProviderDescription serviceDescription; + + private static OAuthServiceProviderTokenManager tokenManager; + + /// <summary> + /// The shared service provider object. + /// </summary> + private static ServiceProvider serviceProvider; + + /// <summary> + /// The lock to synchronize initialization of the <see cref="serviceProvider"/> field. + /// </summary> + private static object initializerLock = new object(); + + /// <summary> + /// Gets the service provider. + /// </summary> + /// <value>The service provider.</value> + public static ServiceProvider ServiceProvider { + get { + EnsureInitialized(); + return serviceProvider; + } + } + + /// <summary> + /// Gets the service description. + /// </summary> + /// <value>The service description.</value> + public static ServiceProviderDescription ServiceDescription { + get { + EnsureInitialized(); + return serviceDescription; + } + } + + public static UserAuthorizationRequest PendingAuthorizationRequest { + get { return HttpContext.Current.Session[PendingAuthorizationRequestSessionKey] as UserAuthorizationRequest; } + set { HttpContext.Current.Session[PendingAuthorizationRequestSessionKey] = value; } + } + + public static Consumer PendingAuthorizationConsumer { + get { + ITokenContainingMessage message = PendingAuthorizationRequest; + if (message == null) { + throw new InvalidOperationException(); + } + + return Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().Include("Consumer").First(t => t.Token == message.Token).Consumer; + } + } + + public static void AuthorizePendingRequestToken() { + var pendingRequest = PendingAuthorizationRequest; + if (pendingRequest == null) { + throw new InvalidOperationException("No pending authorization request to authorize."); + } + + ITokenContainingMessage msg = pendingRequest; + var token = Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().First(t => t.Token == msg.Token); + token.Authorize(); + + PendingAuthorizationRequest = null; + var response = serviceProvider.PrepareAuthorizationResponse(pendingRequest); + if (response != null) { + serviceProvider.Channel.Send(response); + } + } + + /// <summary> + /// Initializes the <see cref="serviceProvider"/> field if it has not yet been initialized. + /// </summary> + private static void EnsureInitialized() { + if (serviceProvider == null) { + lock (initializerLock) { + if (serviceDescription == null) { + var postEndpoint = new MessageReceivingEndpoint(new Uri(Utilities.ApplicationRoot, "OAuth.ashx"), HttpDeliveryMethods.PostRequest); + var getEndpoint = new MessageReceivingEndpoint(postEndpoint.Location, HttpDeliveryMethods.GetRequest); + serviceDescription = new ServiceProviderDescription { + TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, + RequestTokenEndpoint = postEndpoint, + AccessTokenEndpoint = postEndpoint, + UserAuthorizationEndpoint = getEndpoint, + }; + } + + if (tokenManager == null) { + tokenManager = new OAuthServiceProviderTokenManager(); + } + + if (serviceProvider == null) { + serviceProvider = new ServiceProvider(serviceDescription, tokenManager); + } + } + } + } + } +} diff --git a/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs new file mode 100644 index 0000000..be53180 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthServiceProviderTokenManager.cs @@ -0,0 +1,112 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthServiceProviderTokenManager.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + using DotNetOpenAuth.OAuth.ChannelElements; + + public class OAuthServiceProviderTokenManager : OAuthTokenManager, IServiceProviderTokenManager { + /// <summary> + /// Initializes a new instance of the <see cref="OAuthServiceProviderTokenManager"/> class. + /// </summary> + public OAuthServiceProviderTokenManager() { + } + + #region IServiceProviderTokenManager Members + + /// <summary> + /// Gets the Consumer description for a given a Consumer Key. + /// </summary> + /// <param name="consumerKey">The Consumer Key.</param> + /// <returns> + /// A description of the consumer. Never null. + /// </returns> + /// <exception cref="KeyNotFoundException">Thrown if the consumer key cannot be found.</exception> + public IConsumerDescription GetConsumer(string consumerKey) { + try { + return Database.DataContext.Consumer.First(c => c.ConsumerKey == consumerKey); + } catch (InvalidOperationException) { + throw new KeyNotFoundException(); + } + } + + /// <summary> + /// Checks whether a given request token has already been authorized + /// by some user for use by the Consumer that requested it. + /// </summary> + /// <param name="requestToken">The Consumer's request token.</param> + /// <returns> + /// True if the request token has already been fully authorized by the user + /// who owns the relevant protected resources. False if the token has not yet + /// been authorized, has expired or does not exist. + /// </returns> + public bool IsRequestTokenAuthorized(string requestToken) { + return Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().Any( + t => t.Token == requestToken && t.User != null); + } + + /// <summary> + /// Gets details on the named request token. + /// </summary> + /// <param name="token">The request token.</param> + /// <returns>A description of the token. Never null.</returns> + /// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception> + /// <remarks> + /// It is acceptable for implementations to find the token, see that it has expired, + /// delete it from the database and then throw <see cref="KeyNotFoundException"/>, + /// or alternatively it can return the expired token anyway and the OAuth channel will + /// log and throw the appropriate error. + /// </remarks> + public IServiceProviderRequestToken GetRequestToken(string token) { + try { + return Database.DataContext.IssuedToken.OfType<IssuedRequestToken>().First(tok => tok.Token == token); + } catch (InvalidOperationException) { + throw new KeyNotFoundException(); + } + } + + /// <summary> + /// Gets details on the named access token. + /// </summary> + /// <param name="token">The access token.</param> + /// <returns>A description of the token. Never null.</returns> + /// <exception cref="KeyNotFoundException">Thrown if the token cannot be found.</exception> + /// <remarks> + /// It is acceptable for implementations to find the token, see that it has expired, + /// delete it from the database and then throw <see cref="KeyNotFoundException"/>, + /// or alternatively it can return the expired token anyway and the OAuth channel will + /// log and throw the appropriate error. + /// </remarks> + public IServiceProviderAccessToken GetAccessToken(string token) { + try { + return Database.DataContext.IssuedToken.OfType<IssuedAccessToken>().First(tok => tok.Token == token); + } catch (InvalidOperationException) { + throw new KeyNotFoundException(); + } + } + + /// <summary> + /// Persists any changes made to the token. + /// </summary> + /// <param name="token">The token whose properties have been changed.</param> + /// <remarks> + /// This library will invoke this method after making a set + /// of changes to the token as part of a web request to give the host + /// the opportunity to persist those changes to a database. + /// Depending on the object persistence framework the host site uses, + /// this method MAY not need to do anything (if changes made to the token + /// will automatically be saved without any extra handling). + /// </remarks> + public void UpdateToken(IServiceProviderRequestToken token) { + Database.DataContext.SaveChanges(); + } + + #endregion + } +} diff --git a/projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs b/projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs new file mode 100644 index 0000000..fbba776 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/OAuthTokenManager.cs @@ -0,0 +1,143 @@ +//----------------------------------------------------------------------- +// <copyright file="OAuthTokenManager.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Security.Cryptography.X509Certificates; + using System.Web; + using DotNetOpenAuth.OAuth; + using DotNetOpenAuth.OAuth.ChannelElements; + using DotNetOpenAuth.OAuth.Messages; + + /// <summary> + /// The token manager this web site uses in its roles both as + /// a consumer and as a service provider. + /// </summary> + public class OAuthTokenManager : ITokenManager { + /// <summary> + /// Initializes a new instance of the <see cref="OAuthTokenManager"/> class. + /// </summary> + protected OAuthTokenManager() { + } + + #region ITokenManager Members + + /// <summary> + /// Gets the Token Secret given a request or access token. + /// </summary> + /// <param name="token">The request or access token.</param> + /// <returns> + /// The secret associated with the given token. + /// </returns> + /// <exception cref="ArgumentException">Thrown if the secret cannot be found for the given token.</exception> + public string GetTokenSecret(string token) { + try { + return Database.DataContext.IssuedToken.First(t => t.Token == token).TokenSecret; + } catch (InvalidOperationException) { + throw new ArgumentOutOfRangeException(); + } + } + + /// <summary> + /// Stores a newly generated unauthorized request token, secret, and optional + /// application-specific parameters for later recall. + /// </summary> + /// <param name="request">The request message that resulted in the generation of a new unauthorized request token.</param> + /// <param name="response">The response message that includes the unauthorized request token.</param> + /// <exception cref="ArgumentException">Thrown if the consumer key is not registered, or a required parameter was not found in the parameters collection.</exception> + /// <remarks> + /// Request tokens stored by this method SHOULD NOT associate any user account with this token. + /// It usually opens up security holes in your application to do so. Instead, you associate a user + /// account with access tokens (not request tokens) in the <see cref="ExpireRequestTokenAndStoreNewAccessToken"/> + /// method. + /// </remarks> + public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response) { + Consumer consumer; + try { + consumer = Database.DataContext.Consumer.First(c => c.ConsumerKey == request.ConsumerKey); + } catch (InvalidOperationException) { + throw new ArgumentOutOfRangeException(); + } + + var token = new IssuedRequestToken { + Callback = request.Callback, + Consumer = consumer, + CreatedOn = DateTime.Now, + Token = response.Token, + TokenSecret = response.TokenSecret, + }; + string scope; + if (request.ExtraData.TryGetValue("scope", out scope)) { + token.Scope = scope; + } + Database.DataContext.AddToIssuedToken(token); + Database.DataContext.SaveChanges(); + } + + /// <summary> + /// Deletes a request token and its associated secret and stores a new access token and secret. + /// </summary> + /// <param name="consumerKey">The Consumer that is exchanging its request token for an access token.</param> + /// <param name="requestToken">The Consumer's request token that should be deleted/expired.</param> + /// <param name="accessToken">The new access token that is being issued to the Consumer.</param> + /// <param name="accessTokenSecret">The secret associated with the newly issued access token.</param> + /// <remarks> + /// <para> + /// Any scope of granted privileges associated with the request token from the + /// original call to <see cref="StoreNewRequestToken"/> should be carried over + /// to the new Access Token. + /// </para> + /// <para> + /// To associate a user account with the new access token, + /// <see cref="System.Web.HttpContext.User">HttpContext.Current.User</see> may be + /// useful in an ASP.NET web application within the implementation of this method. + /// Alternatively you may store the access token here without associating with a user account, + /// and wait until <see cref="WebConsumer.ProcessUserAuthorization()"/> or + /// <see cref="DesktopConsumer.ProcessUserAuthorization(string, string)"/> return the access + /// token to associate the access token with a user account at that point. + /// </para> + /// </remarks> + public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) { + var requestTokenEntity = Database.DataContext.IssuedToken.OfType<IssuedRequestToken>() + .Include("User") + .First(t => t.Consumer.ConsumerKey == consumerKey && t.Token == requestToken); + + var accessTokenEntity = new IssuedAccessToken { + Token = accessToken, + TokenSecret = accessTokenSecret, + ExpirationDate = null, // currently, our access tokens don't expire + CreatedOn = DateTime.Now, + User = requestTokenEntity.User, + Scope = requestTokenEntity.Scope, + Consumer = requestTokenEntity.Consumer, + }; + + Database.DataContext.DeleteObject(requestTokenEntity); + Database.DataContext.AddToIssuedToken(accessTokenEntity); + Database.DataContext.SaveChanges(); + } + + /// <summary> + /// Classifies a token as a request token or an access token. + /// </summary> + /// <param name="token">The token to classify.</param> + /// <returns> + /// Request or Access token, or invalid if the token is not recognized. + /// </returns> + public TokenType GetTokenType(string token) { + IssuedToken tok = Database.DataContext.IssuedToken.FirstOrDefault(t => t.Token == token); + if (tok == null) { + return TokenType.InvalidToken; + } else { + return tok is IssuedAccessToken ? TokenType.AccessToken : TokenType.RequestToken; + } + } + + #endregion + } +} diff --git a/projecttemplates/RelyingPartyLogic/Policies.cs b/projecttemplates/RelyingPartyLogic/Policies.cs new file mode 100644 index 0000000..6bf72d3 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Policies.cs @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------- +// <copyright file="Policies.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Linq; + using System.Web; + + public class Policies { + /// <summary> + /// The set of OP Endpoints that we trust pre-verify email addresses before sending them + /// with positive assertions. + /// </summary> + public static readonly Uri[] ProviderEndpointsProvidingTrustedEmails = new Uri[] { + new Uri("https://www.google.com/accounts/o8/ud"), + new Uri("https://open.login.yahooapis.com/openid/op/auth"), + }; + } +} diff --git a/projecttemplates/RelyingPartyLogic/Properties/AssemblyInfo.cs b/projecttemplates/RelyingPartyLogic/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8cb040c --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("RelyingPartyLogic")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft IT")] +[assembly: AssemblyProduct("RelyingPartyLogic")] +[assembly: AssemblyCopyright("Copyright © Microsoft IT 2009")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("86d51499-3206-4eea-9bfe-b7950dac606b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj new file mode 100644 index 0000000..7000e2b --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/RelyingPartyLogic.csproj @@ -0,0 +1,131 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProductVersion>9.0.30729</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{17932639-1F50-48AF-B0A5-E2BF832F82CC}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>RelyingPartyLogic</RootNamespace> + <AssemblyName>RelyingPartyLogic</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\lib\log4net.dll</HintPath> + </Reference> + <Reference Include="Microsoft.SqlServer.ConnectionInfo" /> + <Reference Include="Microsoft.SqlServer.Smo" /> + <Reference Include="Microsoft.SqlServer.Management.Sdk.Sfc" /> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.Entity"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.IdentityModel"> + <RequiredTargetFramework>3.0</RequiredTargetFramework> + </Reference> + <Reference Include="System.Runtime.Serialization"> + <RequiredTargetFramework>3.0</RequiredTargetFramework> + </Reference> + <Reference Include="System.Security" /> + <Reference Include="System.ServiceModel"> + <RequiredTargetFramework>3.0</RequiredTargetFramework> + </Reference> + <Reference Include="System.Web.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"> + <SpecificVersion>False</SpecificVersion> + <HintPath>..\..\..\Windows\assembly\GAC_MSIL\System.Web.Entity\3.5.0.0__b77a5c561934e089\System.Web.Entity.dll</HintPath> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Web.Extensions"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Xml.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Drawing" /> + <Reference Include="System.Web" /> + <Reference Include="System.Xml" /> + <Reference Include="System.Configuration" /> + <Reference Include="System.Web.Services" /> + <Reference Include="System.EnterpriseServices" /> + <Reference Include="System.Web.Mobile" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Database.cs" /> + <Compile Include="DataRoleProvider.cs" /> + <Compile Include="Model.AuthenticationToken.cs" /> + <Compile Include="Model.Consumer.cs" /> + <Compile Include="Model.Designer.cs"> + <DependentUpon>Model.edmx</DependentUpon> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + </Compile> + <Compile Include="Model.IssuedAccessToken.cs" /> + <Compile Include="Model.IssuedRequestToken.cs" /> + <Compile Include="Model.User.cs" /> + <Compile Include="OAuthAuthenticationModule.cs" /> + <Compile Include="OAuthAuthorizationManager.cs" /> + <Compile Include="OAuthConsumerTokenManager.cs" /> + <Compile Include="OAuthPrincipalAuthorizationPolicy.cs" /> + <Compile Include="OAuthServiceProvider.cs" /> + <Compile Include="OAuthServiceProviderTokenManager.cs" /> + <Compile Include="OAuthTokenManager.cs" /> + <Compile Include="Policies.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="Utilities.cs" /> + </ItemGroup> + <ItemGroup> + <EntityDeploy Include="Model.edmx"> + <Generator>EntityModelCodeGenerator</Generator> + <LastGenOutput>Model.Designer.cs</LastGenOutput> + </EntityDeploy> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\src\DotNetOpenAuth\DotNetOpenAuth.csproj"> + <Project>{3191B653-F76D-4C1A-9A5A-347BC3AAAAB7}</Project> + <Name>DotNetOpenAuth</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="CreateDatabase.sql" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/projecttemplates/RelyingPartyLogic/Utilities.cs b/projecttemplates/RelyingPartyLogic/Utilities.cs new file mode 100644 index 0000000..02eb273 --- /dev/null +++ b/projecttemplates/RelyingPartyLogic/Utilities.cs @@ -0,0 +1,64 @@ +//----------------------------------------------------------------------- +// <copyright file="Utilities.cs" company="Andrew Arnott"> +// Copyright (c) Andrew Arnott. All rights reserved. +// </copyright> +//----------------------------------------------------------------------- + +namespace RelyingPartyLogic { + using System; + using System.Collections.Generic; + using System.Globalization; + using System.IO; + using System.Linq; + using System.Reflection; + using System.Text; + using System.Web; + using DotNetOpenAuth.OpenId; + using Microsoft.SqlServer.Management.Common; + using Microsoft.SqlServer.Management.Smo; + + public class Utilities { + internal const string DefaultNamespace = "RelyingPartyLogic"; + + /// <summary> + /// Gets the full URI of the web application root. Guaranteed to end in a slash. + /// </summary> + public static Uri ApplicationRoot { + get { + string appRoot = HttpContext.Current.Request.ApplicationPath; + if (!appRoot.EndsWith("/", StringComparison.Ordinal)) { + appRoot += "/"; + } + + return new Uri(HttpContext.Current.Request.Url, appRoot); + } + } + + public static void CreateDatabase(Identifier claimedId, string friendlyId) { + const string SqlFormat = @" +CREATE DATABASE [{0}] ON (NAME='{0}', FILENAME='{0}') +GO +USE ""{0}"" +GO +{1} +EXEC [dbo].[AddUser] 'admin', 'admin', '{2}', '{3}' +GO +"; + string schemaSql; + using (var sr = new StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(DefaultNamespace + ".CreateDatabase.sql"))) { + schemaSql = sr.ReadToEnd(); + } + string databasePath = HttpContext.Current.Server.MapPath("~/App_Data/Database.mdf"); + string sql = string.Format(CultureInfo.InvariantCulture, SqlFormat, databasePath, schemaSql, claimedId, "Admin"); + + var serverConnection = new ServerConnection(".\\sqlexpress"); + try { + serverConnection.ExecuteNonQuery(sql); + var server = new Server(serverConnection); + server.DetachDatabase(databasePath, true); + } finally { + serverConnection.Disconnect(); + } + } + } +} |