Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Events
Videos
Audiobooks
Packt Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds

How-To Tutorials

7019 Articles
article-image-creating-view-mysql-query-browser
Packt
23 Oct 2009
2 min read
Save for later

Creating a View with MySQL Query Browser

Packt
23 Oct 2009
2 min read
Please refer to an earlier article by the author to learn how to build queries visually. Creating a View from an Existing Query To create a view from a query, you must have executed the query successfully. To be more precise, the view is created from the latest successfully executed query, not necessarily from the query currently in the Query Area. To further clarify, the following three examples are cases where the view is not created from the current query: Your current query fails, and immediately after you create a view from the query. The view created is not from the failed query. If the failed query is the first query in your MySQL Query Browser session, you can’t create any view. You have just moved forward or backward the query in the Query Area without executing it, and then your current query is not the latest successfully executed. You open a saved query that you have never executed successfully in your active Resultset. Additionally, if you’re changing your Resultset, the view created is from the latest successfully executed query that uses the currently active Resultset to display its output. To make sure your view is from the query you want, select the query, confirm it as written in the Query Area, execute the query, and then, immediately create its view. You create a view from an existing query by selecting Query | Create View from Select from the Menu bar. Type in the name you want to give to the view, and then click Create View. MySQL Query Browser creates the view. When successfully created, you can see the view in the Schemata. You can modify a view by editing it: Right-click the view and select Edit View. You can edit the CREATE view statement by right-clicking it and select Edit View. The CREATE view statement opens in its Script tab. When you finish editing, you can execute the modified view. If successful, the existing view is replaced with the modified one. To replace the view you’re editing with the modified view, change the name of the view before you execute it. If you want to keep the view you’re editing, remove the DROP VIEW statement.
Read more
  • 0
  • 0
  • 5211

article-image-business-blogging-technorati-state-blogosphere-2008
Packt
23 Oct 2009
4 min read
Save for later

Business Blogging On The Up - Technorati State of the Blogosphere 2008

Packt
23 Oct 2009
4 min read
The report also states that blogs are profitable, it says: The majority of bloggers we surveyed currently have advertising on their blogs. Among those with advertising, the mean annual investment in their blog is $1,800, but it’s paying off. The mean annual revenue is $6,000 with $75K+ in revenue for those with 100,000 or more unique visitors per month. It is interesting to note that the majority of bloggers now display advertising. One of the most encouraging statistics is that the proportion of people blogging about their jobs and on behalf of their business is now so high: About half of bloggers are professional bloggers — blogging is not necessarily their full-time job, but they blog about their industry or profession in an unofficial capacity. 12% of bloggers blog in an official capacity for their company. The amount of cross-over between the groups is also interesting. It shows that personal and business blogging can be successfully combined: More than half of professional and corporate bloggers are also personal bloggers. This could be on a separate blog, or they may blog about personal interests within their professional blog. Corporate bloggers: 69% are also personal bloggers 65% are professional bloggers Professional bloggers: 59% are also personal bloggers 17% are corporate bloggers It’s very encouraging to see the positive benefits being enjoyed by business and professional bloggers, with the majority of those surveyed reporting a positive impact as a result of their blog. Half of them say they are better known in their industry and a quarter see their blog as a useful résumé enhancement. Impact of blogging on professional life: Business bloggers also report that blogging has brought many unique opportunities that wouldn’t have otherwise been available. Taking part in an event, contributing to a print publication or even appearing on radio or TV are the kinds of things they are involved in, thanks to their blog. Have you been invited to any of the following as the result of your blog? Blogging is a time consuming activity. This is confirmed by the report which shows that a quarter of bloggers spend over 10 hours per week on their blog and nearly half spend 5 hours or more. Time spent blogging each week: As I mention in WordPress For Business Bloggers, many bloggers take on help to run their blog. This is particularly true for corporate or business bloggers, of whom nearly 20% have paid staff working for them. Blogs with higher Technorati authority are updated more frequently than those with less authority, as the report states: The Technorati Top 100 are prolific, with 43% posting ten times per day or more often. Only 8% post once a day or less frequently, compared to 13% of the next 500 bloggers, and 22% of the next 5000 bloggers. I highlight the importance of using tags in WordPress For Business Bloggers, and this is borne out by the data. Technorati top 100 bloggers are twice as likely to tag their posts. Percentage of bloggers who use tags: Promoting a blog well is key to its success and the report shows us the top traffic-building strategies used. These are particularly important for business bloggers, so all the techniques highlighted in the chart below are covered in WordPress For Business Bloggers, you’ll find many of them in Chapter 7, Supercharged Promotion: The vast majority of bloggers are tracking their site visitors and monthly page views, with Google Analytics being used by two thirds of them. Using Google Analytics with WordPress is covered in detail in the book, WordPress For Business Bloggers. Direct revenue generation is becoming an important aspect of blogging, with the majority of bloggers now displaying ads, affiliate marketing or other form of revenue generation (this subject is covered in detail in Chapter 10 of WordPress For Business Bloggers): The report data seems to suggest that the medium of blogging is gaining credibility and being taken more seriously as a source of information. 37% of bloggers have been quoted in the traditional media as a result of one of their posts. This is encouraging for business bloggers who use their blog as a PR tool. All in all, the State of the Blogosphere 2008 report makes encouraging reading for business bloggers as well as anyone who is thinking about starting a blog for their business. A blog can be a tremendously powerful tool for any business and using a top quality platform like WordPress makes running a blog extremely easy.  
Read more
  • 0
  • 0
  • 1466

article-image-prototyping-javascript
Packt
23 Oct 2009
7 min read
Save for later

Prototyping JavaScript

Packt
23 Oct 2009
7 min read
In this article by Stoyan Stefanov, you'll learn about the prototype property of the function objects. Understanding how the prototype works is an important part of learning the JavaScript language. After all, JavaScript is classified as having a prototype-based object model. There's nothing particularly difficult about the prototype, but it is a new concept and as such may sometimes take some time to sink in. It's one of these things in JavaScript (closures are another) which, once you "get" them, they seem so obvious and make perfect sense. As with the rest of the article, you're strongly encouraged to type in and play around with the examples; this makes it much easier to learn and remember the concepts. The following topics are discussed in this article: Every function has a prototype property and it contains an object Adding properties to the prototype object Using the properties added to the prototype The difference between own properties and properties of the prototype __proto__, the secret link every object keeps to its prototype Methods such as isPrototypeOf(), hasOwnProperty(), and propertyIsEnumerable() The prototype Property The functions in JavaScript are objects and they contain methods and properties. Some of the common methods are apply() and call() and some of the common properties are length and constructor. Another property of the function objects is prototype. If you define a simple function foo() you can access its properties as you would do with any other object: >>>function foo(a, b){return a * b;}>>>foo.length 2 >>>foo.constructor Function() prototype is a property that gets created as soon as you define the function. Its initial value is an empty object. >>>typeof foo.prototype "object" It's as if you added this property yourself like this: >>>foo.prototype = {} You can augment this empty object with properties and methods. They won't have any effect of the foo() function itself; they'll only be used when you use foo()as a constructor. Adding Methods and Properties Using the Prototype Constructor functions can be used to create (construct) new objects. The main idea is that inside a function invoked with new you have access to the value this, which contains the object to be returned by the constructor. Augmenting (adding methods and properties to) this object is the way to add functionality to the object being created. Let's take a look at the constructor function Gadget() which uses this to add two properties and one method to the objects it creates. function Gadget(name, color) {   this.name = name;   this.color = color;   this.whatAreYou = function(){    return 'I am a ' + this.color + ' ' + this.name;   }} Adding methods and properties to the prototype property of the constructor function is another way to add functionality to the objects this constructor produces. Let's add two more properties, price and rating, and a getInfo() method. Since prototype contains an object, you can just keep adding to it like this: Gadget.prototype.price = 100;Gadget.prototype.rating = 3;Gadget.prototype.getInfo = function() {   return 'Rating: ' + this.rating + ', price: ' + this.price;}; Instead of adding to the prototype object, another way to achieve the above result is to overwrite the prototype completely, replacing it with an object of your choice: Gadget.prototype = {   price: 100,   rating: 3,   getInfo: function() {    return 'Rating: ' + this.rating + ', price: ' + this.price;   }}; Using the Prototype's Methods and Properties All the methods and properties you have added to the prototype are directly available as soon as you create a new object using the constructor. If you create a newtoy object using the Gadget() constructor, you can access all the methods and properties already defined. >>> var newtoy = new Gadget('webcam', 'black');>>> newtoy.name; "webcam" >>> newtoy.color; "black" >>> newtoy.whatAreYou(); "I am a black webcam" >>> newtoy.price; 100 >>> newtoy.rating; 3 >>> newtoy.getInfo(); "Rating: 3, price: 100" It's important to note that the prototype is "live". Objects are passed by reference in JavaScript, and therefore the prototype is not copied with every new object instance. What does this mean in practice? It means that you can modify the prototype at any time and all objects (even those created before the modification) will inherit the changes. Let's continue the example, adding a new method to the prototype: Gadget.prototype.get = function(what) {   return this[what];}; Even though newtoy was created before the get() method was defined, newtoy will still have access to the new method: >>> newtoy.get('price'); 100 >>> newtoy.get('color'); "black" Own Properties versus prototype Properties In the example above getInfo() used this internally to address the object. It could've also used Gadget.prototype to achieve the same result: Gadget.prototype.getInfo = function() {   return 'Rating: ' + Gadget.prototype.rating + ', price: ' + Gadget.prototype.price;}; What's is the difference? To answer this question, let's examine how the prototype works in more detail. Let's again take our newtoy object: >>> var newtoy = new Gadget('webcam', 'black'); When you try to access a property of newtoy, say newtoy.name the JavaScript engine will look through all of the properties of the object searching for one called name and, if it finds it, will return its value. >>> newtoy.name "webcam" What if you try to access the rating property? The JavaScript engine will examine all of the properties of newtoy and will not find the one called rating. Then the script engine will identify the prototype of the constructor function used to create this object (same as if you do newtoy.constructor.prototype). If the property is found in the prototype, this property is used. >>> newtoy.rating 3 This would be the same as if you accessed the prototype directly. Every object has a constructor property, which is a reference to the function that created the object, so in our case: >>> newtoy.constructor Gadget(name, color) >>> newtoy.constructor.prototype.rating 3 Now let's take this lookup one step further. Every object has a constructor. The prototype is an object, so it must have a constructor too. Which in turn has a prototype. In other words you can do: >>> newtoy.constructor.prototype.constructor Gadget(name, color) >>> newtoy.constructor.prototype.constructor.prototype Object price=100 rating=3 This might go on for a while, depending on how long the prototype chain is, but you eventually end up with the built-in Object() object, which is the highest-level parent. In practice, this means that if you try newtoy.toString() and newtoy doesn't have an own toString() method and its prototype doesn't either, in the end you'll get the Object's toString() >>> newtoy.toString() "[object Object]" Overwriting Prototype's Property withOwn Property As the above discussion demonstrates, if one of your objects doesn't have a certain property of its own, it can use one (if exists) somewhere up the prototype chain. What if the object does have its own property and the prototype also has one with the same name? The own property takes precedence over the prototype's. Let's have a scenario where a property name exists both as an own property and as a property of the prototype object: function Gadget(name) {   this.name = name;}Gadget.prototype.name = 'foo'; "foo" Creating a new object and accessing its name property gives you the object's ownname property. >>> var toy = new Gadget('camera');>>> toy.name; "camera" If you delete this property, the prototype's property with the same name"shines through": >>> delete toy.name; true >>> toy.name; "foo" Of course, you can always re-create the object's own property: >>> toy.name = 'camera';>>> toy.name; "camera"  
Read more
  • 0
  • 0
  • 6696

article-image-openid-ultimate-sign
Packt
23 Oct 2009
13 min read
Save for later

OpenID: The Ultimate Sign On

Packt
23 Oct 2009
13 min read
Introduction How many times have you walked away from some Internet forum because you could not remember your login ID or password, and just did not want to go through the tedium of registering again? Or gone back to re-register yourself only to forget you password the next day? Remembering all those login IDs and passwords is indeed an onerous task and one more registration for a new site seems like one too many. We have all tried to get around these problems by jotting down passwords on pieces of paper or sticking notes to our terminal – all potentially dangerous practices that defeat the very purpose of keeping a digital identity secure. If you had the choice of a single user ID and password combination – essentially a single digital identity – imagine how easy it might become to sign up or sign in to new sites. Suppose you could also host your own digital identity or get it hosted by third party providers who you could change at will, or create different identity profiles for different classes of sites, or choose when your User ID with a particular site should expire; suppose you could do all this and more in a free, non-proprietary, open standards based, extensible, community-driven framework (whew!) with Open Source libraries and helpful tutorials to get you on board, you would say: “OpenID”. To borrow a quote from the OpenID website openid.net: “OpenID is an open, decentralized, free framework for user-centric digital identity.” The Concept The concept itself is not new (and there are proprietary authentication frameworks already in existence). We are all aware of reference checks or identity documents where a reliable agency is asked to vouch for your credentials. A Passport or a Driver's License is a familiar example. Web sites, especially those that transact business, have digital certificates provided by a reliable Certification Authority so that they can prove to you, the site visitor, they are indeed who they claim to be. From here, it does not require a great stretch of imagination to appreciate that an individual netizen can have his or her own digital identity based on similar principles. This is how you get the show on the road. First, you need to get yourself a personal identity based on OpenID from one of the numerous OpenID providers[1] or some sites that provide an OpenID with membership. This personal identity comes in the form a URL or URI (essentially a web address that starts with http:// or https://) that is unique to you. When you need to sign up or sign in to a web site that accepts OpenID logins (look for the words 'OpenID' or the OpenID logo), you submit your OpenID URL. The web site then redirects you to the site of your ID provider where you authenticate yourself with your password and optionally choose the details – such as full name, e-mail ID, or nickname, or when your login ID should expire for a particular site – that you want to share with the requesting site and allow the authentication request to go through. You are then returned to the requesting site. That is all there is to it. You are authenticated! The requesting site will usually ask you to associate a nickname with your OpenID. It should be possible to register with and sign in to different sites using different nicknames – one for each site – but the same OpenID. But you may not want to overdo this lest you get into trouble trying to recall the right nickname for a particular site. Just Enough Detail This is not a technical how-to. For serious technical details, you can follow the excellent links in the References section. This is a basic guide to get you started with OpenID, to show you how flexible it is, and to give pointers to its technical intricacies. By the end of this article you should be able to create your own personal digital identities based on OpenID (or discover if you already have one – you just might!), and be able to use them effectively. In the following sections, I have used some real web sites as examples. These are only for the purpose of illustration and in no way shows any preference or endorsement. Getting Your OpenID The simplest and most direct way to get your personal OpenID is to go to a third party provider. But before that, the smart thing to do would be find out if you already have one. For instance, if you blog at wordpress.com, then http://yourblogname.wordpress.com is an OpenID already available to you. There are other sites[1], too, that automatically provide you an OpenID with membership. Yahoo! gives you an OpenID if you have an account with them; but it is not automatic and you need to sign up for it at http://openid.yahoo.com. Your OpenID at Yahoo! will be of the form https://me.yahoo.com/your-nickname. To get your third party hosted OpenID we will choose Verisignlab's Personal Identity Provider (PIP) site -- http://pip.verisignlabs.com/ as an example. You are of course free to decide and choose your own provider(s). The sign up form is a simple no-fuss affair with the minimum number of fields. (If you are tired of hearing 'third party', the reason for using the term will get clearer further on. For the purpose of this article, you, the owner of the OpenID are the first party, the web site that wants you authenticated is the second party, the OpenID provider being the third.) After replying to the confirmation e-mail you are ready to take on the wide world with your OpenID. If you gave your ID as 'johndoe' then you will get an OpenID like: http://johndoe.pip.verisignlabs.com. You can come back to the PIP site and update your profile; some sites request information such as full name or e-mail ID but you are always in control whether you want to pass on this information back to them. If you choose to have just one OpenID, then this is about as much as you would ever do to sign on to any OpenID enabled site. You can also create multiple OpenID's for yourself – remember what we said earlier about having multiple ID's to suite different classes of sites. Testing Your OpenID Now that we have our OpenID we will test it and in the process also see how a typical OpenID-based authentication works in practice. Use the testing form[7] in the References section and enter your OpenID URL that you want tested. When you are redirected to your PIP's site (we are sticking to our Verisign example), enter your password and also choose what information you want passed back to the requesting site before clicking “Allow” to let the authentication go through. Important tip: Enter your password only on the PIP's site and nowhere else! Be aware that this particular testing page may not work with all OpenIDs; that may not necessarily mean that the OpenID itself has a problem. Step-by-Step: Use your WordPress or Verisign OpenID For this tutorial part, we will take the example of http://www.propeller.com (a voting site among other things) that accepts OpenID sign ups and sign ins. For an OpenID we will use the URL of your WordPress blog – http://yourblogname.wordpress.com. You could also use your OpenID URL (the one you got from the Verisign example) and follow through. On the Propeller site, go to the sign up page. Look for the prominent OpenID logo. Type in your OpenID URL and click on the 'Verify ...' button. You are taken to the site of your PIP where you need to authenticate yourself.   If you used your Verisign OpenID, enter your password, complete the details you want to pass back to the requesting site (remember, we are trying to sign up with Propeller) and allow the authentication to go through. You are now back with the Propeller site. Just hang in there a moment as we check the flow for a Wordpress OpenID.   For a WordPress OpenID, you will get a screen instead that asks you to deliberately sign in to your WordPress account. Once you are signed in, you will see a hyperlink that prompts you to continue with the authentication request from Propeller.     Follow this link to a form that asks your permission to pass back information to Propeller such your nickname and e-mail ID. You can change both these fields if you wish and allow the authentication to go through.   Now you should be back at the Propeller site with a successful OpenID verification. The site will ask you to associate a nickname with your OpenID and a working e-mail to complete your registration process. This step is no different from a normal sign up process. Check your e-mail, click on the link provided therein, get back to the Propeller site, and click another link to complete the registration process. You are automatically signed in to Propeller. Sign out for the moment so that we can see how an OpenID sign in works. Go to the sign in page at Propeller. You will see a normal sign in and an OpenID sign in. We will use the OpenID one (of course!). Type in your OpenID URL and click on the “Sign in...” button. Complete the formalities on your PIP site (for Verisign you will get a sign in page; for Wordpress you will need to sign in first unless you are already signed in) and let the authentication go through. This time you are back on the Propeller site all signed in and ready to go. Note that your nickname appears correctly because your OpenID is associated with it. That is all there is to it. Easier done than said. Try this a couple of times and I bet it will feel easier than the remote control of your home entertainment system! Your Custom OpenID URL If you want a personalized OpenID URL and do not like the one provided by your PIP you can always use delegation to get what you want. To make your blog or personal home page as your OpenID URL, insert the following in the head portion (the part that falls between <head> and </head> on an HTML page) of your blog or any page that you own. This will only work with pages that you completely own and have control over their source. There is a Wordpress plug-in that gives delegating capability to your Wordpress.com blog but we will not go into that here. The first URL is your OpenID server. The second URL is your OpenID URL – either the one you host yourself or the one provided by a third party. The requesting site discovers your OpenID and correctly authenticates you. With this approach you can switch providers transparently. At the risk of repeating: test your new personalized URL before you start using it. Note that the 'openid.server' URL may vary depending on the PIP. To get the name of your PIP's OpenID server, use the testing service[7] which reports the correct URL for your PIP to use with the “openid.server” part your delegation mark up. <link rel="openid.server" href="http://pip.verisignlabs.com/server" /><link rel="openid.delegate" href="http://johndoe.pip.verisignlabs.com/" /> Rolling Your Own If you are paranoid about entrusting the management of your digital identity to another web site and also have the technical smarts to match, there are ways you can become your own PIP[5][6]. If you are tech-savvy then you cannot fail to appreciate the elegance of the OpenID architecture and the way it lets control stay where it should – with you. Account Management – Lite? OpenID makes life easier for site visitors. But what about the site and the domain administrators? If administrators decide to go the OpenID way[3], it lightens their load by taking away a major part of the chore of membership administration and authentication. As a bonus, it also potentially opens up a site to the entire community of net users that have OpenID's or are getting one. Security and Reliability As the wisecrack goes – if you want complete security, you should unplug from the Internet. On a serious note, there are some precautions you have to take while using OpenID and they are no different from the precautions you would take for any item associated with your identity, say your Passport or your credit card. Remember to enter your password only on the Identity Provider's site and nowhere else. Be alert to phishing. This explains why WordPress asks you to log in explicitly rather than take you directly to their authentication page. Never use your e-mail ID handle as your OpenID name but use a different one. Using OpenID has its flip side, too. Getting your OpenID from a provider potentially lays open your browsing habits to tracking. You can get around this by being your own PIP, delegating from your own domain, or creating a PIP profile under an alias. There is the possibility that your OpenID provider goes out of service or worse, out of business. It is thus important to choose a reliable identity provider. There are sites that allow you to associate multiple OpenIDs with your account and perhaps this can be a way forward to popularize OpenID and to allay any fears of getting locked in with a single vendor and getting locked out of your identity in the process. Your Call There are many sites today that are not OpenID-ready. There are some sites that allow only OpenID sign ons. However, if you see the elegance of the OpenID mechanism and the convenience it provides both site administrators and members, you might agree that its time has come. Get an OpenID if you do not have one. Convince your friends to get theirs. And if you run an online community or are a member of one, throw your weight around to ensure that your site also provides an OpenID sign on. References http://wiki.openid.net/OpenIDServers is a list of ID providers. http://blogs.zdnet.com/digitalID/?p=78 makes a strong case for OpenID. Read it to get a good perspective on the subject. http://www.plaxo.com/api/openid_recipe is a soup-to-nuts tutorial on how to enable your site for OpenID authentication or migrate to OpenID from your current site-specific authentication scheme. Check out http://www.openidenabled.com/php-openid/ if you are looking for software libraries to OpenID-enable your site. http://www.intertwingly.net/blog/2007/01/03/OpenID-for-non-SuperUsers is a crisp if intermediate-level how-to that lets you try out new things in the OpenID space. http://siege.org/projects/phpMyID/ shows you how you can run your own (yes, your own) PIP server. http://www.openidenabled.com/resources/openid-test/checkup is a link that helps you test your OpenID. Once you get your OpenID, you can submit it to the form on this URL and get yourself authenticated to see if everything works fine. Does not seem to work with Wordpress and Yahoo! OpenIDs as of this writing. http://www.openid.net is the OpenID site.   Read another article by Gurudutt Talgery Podcasting with Linux Command Line Tools and Audacity  
Read more
  • 0
  • 0
  • 5681

article-image-photoshop-foundation-difference-between-vector-and-bitmap-graphics
Packt
23 Oct 2009
4 min read
Save for later

Photoshop Foundation - The Difference between Vector and Bitmap Graphics

Packt
23 Oct 2009
4 min read
Introduction Welcome to the first in a new series of articles on Photoshop - the Photoshop Foundations series. The aim of this series is to give both beginners and more experienced users all the information they need to use Photoshop as efficiently as possible. Photoshop is a huge application, and there is usually more than one way to look at a given subject, or perform a certain action. This series aims to both, guide you through the more confusing aspects of Photoshop and show you the very best ways to use this application. In this first article we are going to look at the difference between vector and bitmap graphics, which is one of the most important principles to understand when working with graphics on a computer, inside or outside of Photoshop. Although Photoshop primarily is a bitmap image editor, it is capable of handling vector graphics to a certain extent. This can be a little confusing for people new to creating graphics on a computer, but by the end of this article you should have a clear idea of the difference between these two types of graphics. Bitmap Graphics Bitmap graphics are made up of colored pixels. Pixels are very small rectangles (usually square, although in some video applications they are wider than they are tall) of varying colors that once put together give you an image. You can see from the example below that zooming in on a bitmap image reveals the pixels that make up the image when viewed at 100%.   Bitmap graphics are usually (but not always) photographic in nature, capable of subtle graduated tones - often in the range of millions of colors per image. The problem with bitmap graphics is that they don't enlarge well as Photoshop needs to guess what color the extra pixels should be - this can result is loss of definition and a dramatic lowering in quality, depending on how much you enlarge the image. Common file formats for bitmap image data include GIF, JPEG and PNG for Internet usage and TIFF for print usage. As you can see from the example below, physically enlarging an image will degrade quality. Pixels are also used to display the image on your computer screen. Common pixel dimensions of computer displays are 1024 wide by 768 high and 1600 wide by 1200 high. The size of a bitmap graphic when viewed on your computer screen is defined by the number of pixels that make up the image - so an image that is 50 pixels wide will look very small on your screen at 100% viewing percentage, whereas an image that is 4000 pixels wide will be larger than your screen at 100% viewing percentage. The printable dimensions of an image are defined by the DPI (dots per inch) - this information is invisibly embedded in the image file. Digital cameras often embed information such as this, that may include the conditions the image was taken in, and even the camera model used. This information is not actually visible in the image, and requires software such as Photoshop to read it. You should not confuse the output DPI of your printer with this figure, which may range from 600-2400DPI - this refers to the density of the dots of ink laid down on the page by the printer. You don't have to prepare your images to 2400 DPI to get the best results - in fact doing so will significantly slow down printing as your file could potentially be huge! Often an image DPI in the range of 175-250 will give very good results on home printers. Images prepared for high quality commercial print are usually prepared at 300 DPI for up to A3 in size; whereas very large images (for instance on billboards) can be as low as 50 DPI, as they are not made to be viewed as closely as a magazine or small poster. There is no need to go above 300 DPI when creating images as you will yield virtually no improvement in output quality, only increasing the size of your file when saved. It is easy to understand the relationship between pixel dimensions and DPI - put simply, the DPI is how many pixels will be printed in an inch - so you could actually think of DPI as PPI (pixels per inch). Indeed, many experts believe this to be the true definition of DPI, and that Photoshop should refer to it as such. However, the term DPI is used throughout the professional print industry, so this is why it is referred to as DPI in Photoshop, not PPI.
Read more
  • 0
  • 0
  • 12849

article-image-integrating-zen-cart-content-management-systems
Packt
23 Oct 2009
19 min read
Save for later

Integrating Zen Cart with Content Management Systems

Packt
23 Oct 2009
19 min read
How to Integrate with CMS? While attempting integration of one CMS with another, some simple principles should be remembered. For all integration attempts, you have to consider the following aspects: Master-slave relationship: While integrating one CMS with the other, one of the applications act as the master and the other as the slave. If you integrate application A to application B, then application B will be considered as master. Master applications maintain authentication and sessions for both applications. While integrating Zen Cart with some other CMS, first consider whether Zen Cart will be the master or the slave. If you are integrating Zen Cart with an existing website, Zen Cart is going to be the slave. On the other hand, when you are adding blogging functionality to the Zen Cart shop by integrating WordPress with Zen Cart, Zen Cart is going to be the master. User and Group Management: One purpose of integrating two CMSs is to have a common user and group management system. Zen Cart integration may be tight, where both Zen Cart and an other CMS will use the same database for user and group management. On the other hand, loose integration will allow periodic or event-based synchronization of user or group databases. Tight integration becomes easier when both CMSs use the same type of user database. If the user databases are very different from each other, then tight integration may not be possible and some sort of fallback solution such as synchronizing the databases may be used. Visual integration: Users see the integration only through the visual integration. In fact, visual integration should be such that users will be unaware of integration attempt. While integrating the two CMSs, the visual template of the master should preferably be used for both CMSs. However, using a master's template system is difficult and a central template system should be developed which can be used for both applications. Now, we will see how to integrate Zen Cart with other CMSs. You will notice that at least one of the above-mentioned aspects is present in such integrations. Joomla!/Mambo If you are using Joomla!/Mambo and want e-commerce functionality, you have a number of choices. Among these, the best one is using the VirtueMart component. The VirtueMart component for Joomla!/Mambo is quite similar to Zen Cart or osCommerce. Only a few features of Zen Cart or osCommerce are missing in VirtueMart. However, if you still want to integrate Zen Cart into the existing Joomla!/Mambo website, you have two options-and neither is easier than the other: Use Zen Cart as a wrapper or, develop a component based on Zen Cart. Using Zen Cart as a wrapper is in its true sense not an integration. It runs separately and Joomla! provides a menu link. Clicking on this link will show Zen Cart in a wrapper window. If you are experienced with Joomla! or Mambo, you can figure out how a menu item can be added to show the application in a wrapper. However, adding a wrapper may appear to be an integration if you modify the Zen Cart template accordingly. As the Zen Cart shop appears in the wrapper, it would be wise not to use headers and sidebars in the Zen Cart template. Links to the categories and other menus can be provided in the headers. A separate login mechanism should also be provided in the Zen Cart template. Developing a bridge for Zen Cart and Joomla! is a hot topic in the Zen Cart forum. Users of both Joomla! and Zen Cart agree that integration or bridging of these two will be of great value. However, due to the framework of these two systems, developing such a bridge has some complexities and takes some time. Recently, a discussion on this topic has led to the development of such a bridge by the open-source enthusiasts. Please watch the following thread:http://tinyurl.com/65ypyu. Another possibility is JFusion plug-in for Joomla! (available at www.jfusion.org) which is a framework for integrating several forums to Joomla!. The developer of JFusion has proposed developing such a plug-in for Zen Cart as well. It is hoped that JFusion will be able to integrate Zen Cart to Joomla! soon. Drupal Drupal is a powerful CMS and is widely used. There are a wide range of modules available for Drupal and it is used for different types of websites. There are a great number of Drupal users who want to integrate Drupal and Zen Cart-as both are considered useful in their category. Until recently, there was no easy way to integrate Drupal and Zen Cart. Very recently, Zen Cart Integration module has been released as a development version. For now, it works on Drupal 5.x and Zen Cart 1.3.7. Once this module is installed and configured, you can create Zen Cart categories and products from Drupal. As other nodes, these products and categories will be displayed as nodes in Drupal. When visitors click on these products they see product details as a Drupal node, but when the product is added to cart, it redirects to the Zen Cart shop. This module also provides a single sign-on facility. For integrating Zen Cart into Drupal, download the module from http://drupal.org/project/zencart. Before we proceed with the integration of Drupal and Zen Cart, assume that you have installed Drupal and Zen Cart on the same server. Let us suppose, Drupal is installed in e:wwwdrupal57 directory and Zen Cart 1.3.7 is in e:wwwzc directory, and these two uses separate database on the same MySQL server. Follow these steps: Download and unzip Zen Cart integration module: For integrating Zen Cart into Drupal, download the module from http://drupal.org/project/zencart. On your computer, unzip the zencart-5.x-1.x-dev.tar.gz package. You will get a folder named zencart, under which there are some files and a subfolder named zencart. Copy files for Zen Cart: Inside the zencart subfolder you will find the includes folder. Copy this subfolder, that is /zencart/includes, to your Zen Cart installation directory, that is e:wwwzc. This will overwrite the e:wwwzcincludes directory, but will not overwrite any files. Once you have copied all the files in this folder, you are finished with Zen Cart. Install Zen Cart installation module in Drupal: Copy the zencart directory with all the files inside it, except the zencart subfolder, to Drupal's installation directory, that is e:wwwdrupal57. As an administrator in Drupal, you can install this module from Drupal's Administer | Site Building | Modules section. In the module list you will see the Zen Cart Integration module group. You will find the following modules in this group: Zencart-This is the main module for integrating Zen Cart shopping cart to Drupal. This is required by other modules in this group. Zencart Catalog-This module allows creation of Drupal nodes for Zen Cart products and categories. Zencart Category Node Hierarchy-This module depends on the Node Hierarchy module and organizes Zen Cart products and categories. Download the Node Hirarchy module from http://drupal.org/project/nodehierarchy and install it before enabling this module. To enable these modules, select checkboxes in Enabled column and click Save configuration button at the bottom of the list. Configure Zencart Integration module in Drupal: After enabling the modules, you can configure those from Administer | Site Configuration | Zencart Integration screen. The Zen Cart Status section will provide you information about your Zen Cart installation. The module will search and find the Zen Cart installation and show its version, path to Drupal installation and other information. The Zen Cart Settings section will give you the opportunity to mention the Zen Cart installation directory path. Type it into the Path to Zencart field. The Zen Cart Page Redirects section allows you to configure page redirects from the Zen Cart page to Drupal node. Zen Cart Catalog section allows you to configure redirect from the Zen Cart catalog items to Drupal. While using this integration module, you create Zen Cart catalog and products from Drupal. If you want to create these categories and products from inside Zen Cart and synchronize those with Drupal, then check Update product info on cron. This will synchronize product information both on Drupal and Zen Cart by running cron command on linux/unix. Checking Redirect Product Info Pages will automatically redirect visitors from the Zen Cart product info pages to equivalent Drupal nodes. Similarly, checking Redirect Category Listing Pages will automatically redirect visitors from the Zen Cart category pages to equivalent Drupal nodes. The Zen Cart Users section allows you to configure single sign-on options for Drupal and Zen Cart. If you want to allow Zen Cart existing customers to login to Drupal, then check the Allow Zen Cart Customers to login to Drupal checkbox. On the other hand, if you want to allow Drupal users to login to Zen Cart as customers, check Allow Drupal Users Customers to login to Zen Cart as Customers. Checking Allow Single Sign-On will allow users to login once and access both Drupal and Zen Cart.                                                                                                                                                                                                                                                                                                         The Zencart Integration screen has the following sections: Once you have configured these options, click the Save configuration button, or revert to defaults by clicking the Reset to defaults button. Create Content Type in Drupal for Zen Cart categories and products: If you have ever used Drupal, you know how to create content types in Drupal. You can add new content type from Administer | Content Management | Content types | Add content type. Now you will get a Zen Cart Catalog group. From this section you can define whether this type will be used as a Zen Cart product or category. You can also configure node hierarchy-ability to be parent or child (default is parent). In the Identification section, type a human readable name, for example Zen Cart Product, in the Name field. Then type a machine readable name of this content type, for example zc_product, in the Type field. Provide a description of this content type in the Description field. In the Submission Form section, provide a label for the title and body field, minimum number of words, and explanation or submission guidelines. Configure default options in the Workflow section. Finally, click the Save content type button. Create two content types—one for the Zen Cart category and another for the Zen Cart product. Add Category and Product in Drupal: You can create categories and products from Create Content section. In the list, click on Zen Cart Category. This will open Submit Zen Cart Category form. In this form, type the category name in Title field, type a description of this category in Body field. In the Node Hierarchy section, you can select a parent category. Check Category is Active to make this category visible. Configure other options like Menu settings, URL path settings, Publishing options, and so on and click the Submit button to create the category Similarly, you can create Zen Cart products by clicking on the Zen Cart Product content type. This will display the Submit Zen Cart Product form. Fill in the Submit Zen Cart Product form with appropriate information, such as product name, model, quantity in stock, tax class, base price, and so on. You can select its parent category in the Node Hierarchy section. Check the Create Menu option to make a menu item for this product. Configure other options like Menu settings, URL path settings, Publishing options, and so on and click the Submit button to create the product. Test Zen Cart Integration to and from Drupal: Now it is time to test whether the Drupal-Zen Cart integration is working or not. First, go to your Zen Cart shop, for example, http://localhost/zc. There you will find the categories and products you have added. Click on any of these, and you will be redirected to the respective Drupal node. Again, in the Drupal, click on a product link, type a quantity and click the Add to Cart button. That will redirect you to the Zen Cart shop's Your Shopping Cart Contents page. Similarly you can test single sign-on features by signing in to either Drupal or Zen Cart and trying to purchase items from these two shops. Gallery2 Gallery2 is a web-based software product that lets you manage photos on your own website. It creates a catalog of photos which visitors can view as thumbnails as well as in its original size. It has an intuitive interface to create and maintain albums. It can create thumbnails automatically and can be used for image resizing, rotation, ordering, captioning, searching, and some other functions. You can use Gallery2 to build a community site for sharing photos. You can create the community using Gallery2 and registered users can share their photographs by uploading their own photos. You need to integrate Gallery2 with Zen Cart if you want to sell photos from your photo gallery. Gallery2 has a great mechanism to integrate with Zen Cart. The Gallery2/Zen Cart integration module is available at the Gallery2 download site http://dakanji.com/g2stuff/zcg2-3_2_1a-full.zip. Using it, users can organize their photos and other multimedia files into Gallery2, and offer them for sale through Zen Cart. In integrating Gallery2 with Zen Cart, you have to configure Zen Cart first. Follow these steps for Zen Cart: Download the Gallery2/Zen Cart Integration module and extract it. Copy the zencart/includes folder into your Zen Cart installation directory. This directory contains some templates for Zen Cart. Copying these files will not overwrite any existing file. Login to your Zen Cart administration panel and create a new product category, such as Photographs. Photo items from Gallery2 will go to this category. Select Tools | Template Selection and choose one of the Gallery2 Integration templates provided. You can take a copy of the template folder (../includes/templates/pgxxx) and modify stylesheet.css. You can also modify these templates. Edit ../includes/languages/pgxxx/english.php if you want to change language strings or date formats. Replace ../includes/templates/pgxxx/images/logo.gif with your site's logo. Remember that for Gallery2/Zen Cart integration, both Zen Cart and Gallery2 data tables need to be in one database. In Gallery2, you need to make the following changes: Upload the module files in the gallery2/ directory to your Gallery2 installation's modules directory. In Gallery2 Site Administration, click on Plugins and find Zen Cart under the Commerce heading. Then click Install. After Installation, click Configure. Enter the entire server path to your Zen Cart installation, for example, /home/your_name/public_html/zencart/. Select the category you created in Zen Cart earlier (for example Photographs) from the drop-down menu. Click activate next to the Zen Cart listing on the module page. Refresh the page and click on the Zen Cart link under Admin Options to edit product details. Edit permissions for the individual items as you wish. The module will have assigned permissions to non-album items on activation. If you do not want to sell an item, you will need to disable that item in Zen Cart as the module adds all data items in your gallery to Zen Cart. You can add photograph items from Gallery2. Adding any item to the Gallery2 album will simply show that item in Zen Cart. You can add product options from Gallery2 by clicking on the Zen Cart link in your Gallery2 site administration menu. When you have installed the Gallery2/Zen Cart bridge, you will find a product type in Zen cart named Product-Gallery. All the items from Gallery2 need to be of this type. If you edit any item from Zen Cart and change the product type of any Gallery2 item, the link with the Gallery2 will be broken. Also, note that the Gallery2 bridge will co-exist with Zen Cart image handler and lightbox add-on for Zen Cart. These will handle product images for Zen Cart, whereas Gallery2 add-on only handles images added in Gallery2. You cannot assign the Main category in Zen Cart as the root product category for Gallery2. The category you are selecting in the Gallery2 bridge configuration must be a sub-category product. Once the configurations are done, you can see the photographs from Zen Cart. Visitors can also order photographs from Zen Cart. While you are in Gallery2, you can also place an order by clicking the add to cart link, which is redirected to Zen Cart. WordPress WordPress is an extremely powerful and widely used open-source blogging platform. It has a wide community of developers and users, and almost all kinds of plugins are available for it. Although there are some shopping cart plugins for WordPress, they are not full-blown shopping carts like Zen Cart or osCommerce. E-commerce plug-ins available for WordPress have limited features. Those who are running blogs using WordPress may want to integrate it with Zen Cart to provide e-commerce functionality to their blogs. In fact, there is a Zen Cart module for integrating these two. You can download that module from www.zen-cart.com. After downloading the plug-in WordPress on Zen Cart, you have to install it on the webserver. You can install the plug-in in two ways: first, in an environment where you have a working WordPress installation, and second, when you have not installed WordPress. WordPress and Zen Cart Installed in Separate Directories When you have an existing installation of WordPress, generally it will be in a separate directory from that of the Zen Cart installation. If your web document root directory is public_html, then the installation directories may be: /public_html/blog and /public_html/shop. Follow these procedures to install WordPress on Zen Cart plug-in: Step1: Install WordPress If you have not installed WordPress yet, then download the WordPress files from www.wordpress.org and unzip the files. Then, upload the files to your webserver's /public_html/blog directory. Now, change the permission of this directory to 777 and point your browser to http://yourdomain.com/blog/wp-admin/setup-config.php. The installation wizard for WordPress will be displayed. Follow the instructions on the wizard and give the necessary information. Once all of the information is given, WordPress will be installed. Step 2: Configure WordPress During installation, an administrative account will be created. Note the username and password for this account. Then, point your browser to http://yourdomain.com/blog/wp-admin/. The login page will be displayed. Type the username and password for the administrative account and click on the Login button. You will see the dashboard for administering WordPress. Go to Options | General. Now, change the Blog Address (URL) to Zen Cart's URL http://yourdomain.com/shop/. From the administration dashboard, go to Presentation | Themes and select WordPress Default 1.6. Step 3: Upload WordPress on Zen Cart When you unzip the WordPress on Zen Cart plug-in zip file, you will find that there is a directory called ZC_ROOT and WP_ROOT. Now, upload the contents of ZC_ROOT directory to Zen Cart's installation path on the server, that is, /public_html/shop/. Similarly, upload the contents of the WP_ROOT directory to WordPress' installation path, that is, /public_html/blog. Before uploading the contents of the ZC_ROOT directory, please change the name of the /ZC_ROOT/includes/templates/MY_TEMP/ directory to that of the template directory you are using for your Zen Cart shop Step 4: Edit WordPress File For older versions of WordPress, you may need to edit the /wp-include/template-loader.php file. Open the file in a text editor and replace all exit; with return;. However, you may not need this for the newer versions of WordPress. WordPress 2.3.1 can work without this modification. First, try without this modification. Step 5: Edit Zen Cart File You also need to edit another file in the Zen Cart installation. Open the /includes/extra_configures/wordpress-config.php file under the Zen Cart installation folder and find the following line: define ('ABSPATH','/var/www/vhost/example.com/public_html/blog/'); Type the appropriate WordPress path, that is, /home/username/public_html/blog/. The above line will look like this: define ('ABSPATH','/home/suhreed/public_html/blog/'); If you are trying it on Windows, you may need to put the absolute path, as in, e:/www/blog. Step 6: Configure Sideboxes from Layout Boxes Controller Once the file modifications have been done, login to the Zen Cart administration panel. Go to Tools | Layout Boxes Controller. The screen will notify you that some new sideboxes-wp_cats.php, wp_archives.php, wp_pages.php, wp_links.php, and wp_sidebar.php-have been found. To use these sidebars, click on the reset button at the bottom. To show these sideboxes on your Zen Cart shop, click on the sidebar and change its left/right column status.
Read more
  • 0
  • 0
  • 3736
Unlock access to the largest independent learning library in Tech for FREE!
Get unlimited access to 7500+ expert-authored eBooks and video courses covering every tech area you can think of.
Renews at $19.99/month. Cancel anytime
article-image-search-engines-coldfusion
Packt
23 Oct 2009
5 min read
Save for later

Search Engines in ColdFusion

Packt
23 Oct 2009
5 min read
Built-In Search Engine Verity comes in package with ColdFusion. One of the reasons why people pay for ColdFusion is the incredible power that comes with this tool. It should be noted that one of the most powerful standalone commercial search engines is this tool. Some of the biggest companies in the world have expanded internal services with the help of the Verity tool that we will learn about. We can see that in order to start, we must create collections. The building of search abilities is a three-step process. There is a standard ColdFusion tag to help us with each of these functions. Create collections Index the collections Search the collections These collections can contain information about web pages, binary documents, and can even work as a powerful way to search cached query result information. There are many document formats supported. In the real business world, the latest bleeding-edge solutions will still store a previous version. Archived and shared documents should be stored in appropriate formats and versions that can be searched. Creating a Collection The first thing is to make our collection. See the ColdFusion Administrator under Data & Services. Here, we will be able to add collections and edit existing collections. There is one default collection included in ColdFusion installations. This is the bookclub demonstration application data. We will be creating a collection of PDF documents for this lesson. We have placed a collection of ColdFusion, Flex, and some of the Fusion Authority Quarterly periodicals in a directory for indexing. Here is the information screen for adding the collection through the administrator. We choose to select the Enable Category Support option. Also, there are libraries available for multiple languages if that is appropriate in a collection. We now see that there is a new collection for our devdocs. There are four icons to work with this collection. They are, from right to left, index, optimize, purge, and remove actions. The Name link takes us to the index action. The collection gives us the number of actual documents present, and the size of the index file on the server. The screen will show the details of the index as to when it was last modified, and the language in which it is stored. It lists the categories, and also shows the actual path where the index is stored. Here is a code version of creating a collection that would achieve the same thing. This means that it is possible to create an entire administrative interface to manage collections. It is also possible to move from tags to objects, and wrap up all the functions in that style. <cfcollection action="create" collection="devdocs" path="c:ColdFusion8veritycollectionsdocuments" /> If we have categories in our collection, and we want to get a list of the categories, then the following code must be used: <cfcollection action="categoryList" collection="bookClub" name="myCats" /><cfdump var="#myCats#"> Indexing a Collection We can do this through the administration interface. But here, we will do it as shown in the the following screenshot. This is a limited directory that we have used as an example for searching. This is the result of the devdocs submitted above. This gave a result of 12 documents with a search collection of the size, 4,611 Kb. Now, we will look at how to do the same search using code and build the index outside the administrator interface. This will require the collection to be built before we try to index files into it. The creation of the collection can also be done inside the administration interface or in code. It should also be noted that ColdFusion includes a security called Sandbox Security. These three core tags for Verity searching among many others can be blocked if you find it better for your environment. Just consider what is actually getting indexed and what needs to be searched. Hopefully, documents will be secured correctly and it will not be an issue. When we are making an index, we have to make sure that we can either choose to use a recursive search or not. A recursive search means that all the subdirectories in a document or web page search will be included in our search. It should also be noted that the service will not work for indexing other websites. It is for indexing this server only. <cfindex name="myCats" action="refresh" collection="bookClub" recurse="true" type="path" extensions=".html .htm .cfm .cfml" key="c:inetpubwwwrootdocuments" urlpath="http://localhost/documents/" /> Your collection has been indexed. It is important to note that there is no output from this tag. So we need to put some text on the screen to make sure the person using the site can know that the task has been completed. If we want to index a single file rather than a whole directory path, we can do it with this code: <cfindex action="refresh" collection="bookClub" recurse="true" type="file" extensions=".pdf" key=" c:inetpubwwwrootdocumentsColdFusioncf8_devguide.pdf" urlpath="http://localhost/documents/ColdFusion" /> Your collection has been indexed.
Read more
  • 0
  • 0
  • 2628

article-image-table-and-database-operations-php
Packt
23 Oct 2009
8 min read
Save for later

Table and Database Operations in PHP

Packt
23 Oct 2009
8 min read
Various links that enable table operations have been put together on one sub-page of the Table view: Operations. Here is an overview of this sub-page: Table Maintenance During the lifetime of a table, it repeatedly gets modified, and so grows and shrinks. Outages may occur on the server, leaving some tables in a damaged state. Using the Operations sub-page, we can perform various operations, but not every operation is available for every table type: Check table: Scans all rows to verify that deleted links are correct. Also, a checksum is calculated to verify the integrity of the keys; we should get an 'OK' message if everything is all right. Analyze table: Analyzes and stores the key distribution; this will be used on subsequent JOIN operations to determine the order in which the tables should be joined. Repair table: Repairs any corrupted data for tables in the MyISAM and ARCHIVE engines. Note that the table might be so corrupted that we cannot even go into Table view for it! In such a case, refer to the Multi-Table Operations section for the procedure to repair it. Optimize table: This is useful when the table contains overheads. After massive deletions of rows or length changes for VARCHAR fields, lost bytes remain in the table. PhpMyAdmin warns us in various places (for example, in the Structure view) if it feels the table should be optimized. This operation is a kind of defragmentation for the table. In MySQL 4.x, this operation works only on tables in the MyISAM, Berkeley (BDB), and InnoDB engines. In MySQL 5.x, it works only on tables in the MyISAM, InnoDB, andARCHIVE engines. Flush table: This must be done when there have been lots of connection errors and the MySQL server blocks further connections. Flushing will clear some internal caches and allow normal operations to resume. Defragment table: Random insertions or deletions in an InnoDB table fragment its index. The table should be periodically defragmented for faster data retrieval. The operations are based on the underlying MySQL queries available—phpMyAdmin is only calling those queries. Changing Table Attributes Table attributes are the various properties of a table. This section discusses the settings for some of them. Table Type The first attribute we can change is called Table storage engine: This controls the whole behavior of the table: its location (on-disk or in-memory), the index structure, and whether it supports transactions and foreign keys. The drop-down list may vary depending on the table types supported by our MySQL server. Changing the table type may be a long operation if the number of rows is large. Table Comments This allows us to enter comments for the table. These comments will be shown at appropriate places (for example, in the left panel, next to the table name in the Table view and in the export file). Here is what the left panel looks like when the $cfg['ShowTooltip'] parameter is set to its default value of TRUE: The default value of $cfg['ShowTooltipAliasDB'] and $cfg['ShowTooltipAliasTB'] (FALSE) produces the behavior we have seen earlier: the true database and table names are displayed in the left panel and in the Database view for the Structure sub-page. Comments appear when the mouse pointer is moved over a table name. If one of these parameters is set toTRUE, the corresponding item (database names for DB and table names for TB) will be shown as the tooltip instead of the names. This time, the mouse-over shows the true name for the item. This is convenient when the real table names are not meaningful. There is another possibility for $cfg['ShowTooltipAliasTB']: the 'nested' value. Here is what happens if we use this feature: The true table name is displayed in the left panel. The table comment (for example project__) is interpreted as the project name and is displayed as such. Table Order When we Browse a table or execute a statement such as SELECT * from book, without specifying a sort order, MySQL uses the order in which the rows are physically stored. This table order can be changed with the Alter table order by dialog. We can choose any field, and the table will be reordered once on this field. We choose author_id in the example, and after we click Go, the table gets sorted on this field. Reordering is convenient if we know that we will be retrieving rows in this order most of the time. Moreover, if later we use an ORDER BY clause and the table is already physically sorted on this field, the performance should be higher. This default ordering will last as long as there are no changes in the table (no insertions, deletions, or updates). This is why phpMyAdmin shows the (singly) warning. After the sort has been done on author_id, books for author 1 will be displayed first, followed by the books for author 2, and so on. (We are talking about a default browsing of the table without explicit sorting.) We can also specify the sort order: Ascending or Descending. If we insert another row, describing a new book from author 1, and then click Browse, the book will not be displayed along with the other books for this author because the sort was done before the insertion. Table Options Other attributes that influence the table's behavior may be specified using the Table options dialog: The options are: pack_keys:Setting this attribute results in a smaller index; this can be read faster but takes more time to update. Available for the MyISAM storage engine. checksum: This makes MySQL compute a checksum for each row. This results in slower updates, but easier finding of corrupted tables. Available for MyISAM only. delay_key_write: This instructs MySQL not to write the index updates immediately but to queue them for later, which improves performance. Available for MyISAM only. auto-increment: This changes the auto-increment value. It is shown only if the table's primary key has the auto-increment attribute. Renaming, Moving, and Copying Tables The Rename operation is the easiest to understand: the table simply changes its name and stays in the same database. The Move operation (shown in the following screen) can manipulate a table in two ways: change its name and also the database in which it is stored Moving a table is not directly supported by MySQL, so phpMyAdmin has to create the table in the target database, copy the data, and then finally drop the source table. The Copy operation leaves the original table intact and copies its structure or data (or both) to another table, possibly in another database. Here, the book-copy table will be an exact copy of the book source table. After the copy, we will stay in the Table view for the book table unless we selected Switch to copied table. The Structure only copy is done to create a test table with the same structure. Appending Data to a Table The Copy dialog may also be used to append (add) data from one table to another. Both tables must have the same structure. This operation is achieved by entering the table to which we want to copy the data of the current table and choosing Data only. For example, we would want to append data when book data comes from various sources (various publishers), is stored in more than one table, and we want to aggregate all the data to one place. For MyISAM, a similar result can be obtained by using the MERGE storage engine (which is a collection of identical MyISAM tables), but if the table is InnoDB, we need to rely on phpMyAdmin's Copy feature. Multi-Table Operations In the Database view, there is a checkbox next to each table name and a drop-down menu under the table list. This enables us to quickly choose some tables and perform an operation on all those tables at once. Here we select the book-copy and the book tables, and choose the Check operation for these tables. We could also quickly select or deselect all the checkboxes with Check All/Uncheck All. Repairing an "in use" Table The multi-table mode is the only method (unless we know the exact SQL query to type) for repairing a corrupted table. Such tables may be shown with the in use flag in the database list. Users seeking help in the support forums for phpMyAdmin often receive this tip from experienced phpMyAdmin users. Database Operations The Operations tab in the Database view gives access to a panel that enables us to perform operations on a database taken as a whole. Renaming a Database Starting with phpMyAdmin 2.6.0, a Rename database dialog is available. Although this operation is not directly supported by MySQL, phpMyAdmin does it indirectly by creating a new database, renaming each table (thus sending it to the new database), and dropping the original database. Copying a Database Since phpMyAdmin 2.6.1, it is possible to do a complete copy of a database, even if MySQL itself does not support this operation natively. Summary In this article, we covered the operations we can perform on whole tables or databases. We also took a look at table maintenance operations for table repair and optimization, changing various table attributes, table movements, including renaming and moving to another database, and multi-table operations.
Read more
  • 0
  • 0
  • 5632

article-image-ejb-3-security
Packt
23 Oct 2009
15 min read
Save for later

EJB 3 Security

Packt
23 Oct 2009
15 min read
Authentication and authorization in Java EE Container Security There are two aspects covered by Java EE container security: authentication and authorization. Authentication is the process of verifying that users are who they claim to be. Typically this is performed by the user providing credentials such as a password. Authorization, or access control, is the process of restricting operations to specific users or categories of users. The EJB specification provides two kinds of authorization: declarative and programmatic, as we shall see later in the article. The Java EE security model introduces a few concepts common to both authentication and authorization. A principal is an entity that we wish to authenticate. The format of a principal is application-specific but an example is a username. A role is a logical grouping of principals. For example, we can have administrator, manager, and employee roles. The scope over which a common security policy applies is known as a security domain, or realm. Authentication For authentication, every Java EE compliant application server provides the Java Authentication and Authorization Service (JAAS) API. JAAS supports any underlying security system. So we have a common API regardless of whether authentication is username/password verification against a database, iris or fingerprint recognition for example. The JAAS API is fairly low level and most application servers provide authentication mechanisms at a higher level of abstraction. These authentication mechanisms are application-server specific however. We will not cover JAAS any further here, but look at authentication as provided by the GlassFish application server. GlassFish Authentication There are three actors we need to define on the GlassFish application server for authentication purposes: users, groups, and realms. A user is an entity that we wish to authenticate. A user is synonymous with a principal. A group is a logical grouping of users and is not the same as a role. A group's scope is global to the application server. A role is a logical grouping of users whose scope is limited to a specific application. Of course for some applications we may decide that roles are identical to groups. For other applications we need some mechanism for mapping the roles onto groups. We shall see how this is done later. A realm, as we have seen, is the scope over which a common security policy applies. GlassFish provides three kinds of realms: file, certificate, and admin-realm. The file realm stores user, group, and realm credentials in a file named keyfile. This file is stored within the application server file system. A file realm is used by web clients using http or EJB application clients. The certificate realm stores a digital certificate and is used for authenticating web clients using https. The admin-realm is similar to the file realm and is used for storing administrator credentials. GlassFish comes pre-configured with a default file realm named file. We can add, edit, and delete users, groups, and realms using the GlassFish administrator console. We can also use the create-file-user option of the asadmin command line utility. To add a user named scott to a group named bankemployee, in the file realm, we would use the command: <target name="create-file-user"> <exec executable="${glassfish.home}/bin/asadmin" failonerror="true" vmlauncher="false"> <arg line="create-file-user --user admin --passwordfile userpassword --groups bankemployee scott"/> </exec> </target> --user specifies the GlassFish administrator username, admin in our example. --passwordfile specifies the name of the file containing password entries. In our example this file is userpassword. Users, other than GlassFish administrators, are identified by AS_ADMIN_USERPASSWORD. In our example the content of the userpassword file is: AS_ADMIN_USERPASSWORD=xyz This indicates that the user's password is xyz. --groups specifies the groups associated with this user (there may be more than one group). In our example there is just one group, named bankemployee. Multiple groups are colon delineated. For example if the user belongs to both the bankemployee and bankcustomer groups, we would specify: --groups bankemployee:bankcustomer The final entry is the operand which specifies the name of the user to be created. In our example this is scott. There is a corresponding asadmin delete-file-user option to remove a user from the file realm. Mapping Roles to Groups The Java EE specification specifies that there must be a mechanism for mapping local application specific roles to global roles on the application server. Local roles are used by an EJB for authorization purposes. The actual mapping mechanism is application server specific. As we have seen in the case of GlassFish, the global application server roles are called groups. In GlassFish, local roles are referred to simply as roles. Suppose we want to map an employee role to the bankemployee group. We would need to create a GlassFish specific deployment descriptor, sun-ejb-jar.xml, with the following element: <security-role-mapping> <role-name>employee</role-name> <group-name>bankemployee</group-name> </security-role-mapping> We also need to access the configuration-security screen in the administrator console. We then disable the Default Principal To Role Mapping flag. If the flag is enabled then the default is to map a group onto a role with the same name. So the bankemployee group will be mapped to the bankemployee role. We can leave the default values for the other properties on the configuration-security screen. Many of these features are for advanced use where third party security products can be plugged in or security properties customized. Consequently we will give only a brief description of these properties here. Security Manager: This refers to the JVM security manager which performs code-based security checks. If the security manager is disabled GlassFish will have better performance. However, even if the security manager is disabled, GlassFish still enforces standard Java EE authentication/authorization. Audit Logging: If this is enabled, GlassFish will provide an audit trail of all authentication and authorization decisions through audit modules. Audit modules provide information on incoming requests, outgoing responses and whether authorization was granted or denied. Audit logging applies for web-tier and ejb-tier authentication and authorization. A default audit module is provided but custom audit modules can also be created. Default Realm: This is the default realm used for authentication. Applications use this realm unless they specify a different realm in their deployment descriptor. The default value is file. Other possible values are admin-realm and certificate. We discussed GlassFish realms in the previous section. Default Principal: This is the user name used by GlassFish at run time if no principal is provided. Normally this is not required so the property can be left blank. Default Principal Password: This is the password of the default principal. JACC: This is the class name of a JACC (Java Authorization Contract for Containers) provider. This enables the GlassFish administrator to set up third-party plug in modules conforming to the JACC standard to perform authorization. Audit Modules: If we have created custom modules to perform audit logging, we would select from this list. Mapped Principal Class: This is only applicable when Default Principal to Role Mapping is enabled. The mapped principal class is used to customize the java.security.Principal implementation class used in the default principal to role mapping. If no value is entered, the com.sun.enterprise.deployment.Group implementation of java.security.Principal is used. Authenticating an EJB Application Client Suppose we want to invoke an EJB, BankServiceBean, from an application client. We also want the application client container to authenticate the client. There are a number of steps we first need to take which are application server specific. We will assume that all roles will have the same name as the corresponding application server groups. In the case of GlassFish we need to use the administrator console and enable Default Principal To Role Mapping. Next we need to define a group named bankemployee with one or more associated users. An EJB application client needs to use IOR (Interoperable Object Reference) authentication. The IOR protocol was originally created for CORBA (Common Object Request Broker Architecture) but all Java EE compliant containers support IOR. An EJB deployed on one Java EE compliant vendor may be invoked by a client deployed on another Java EE compliant vendor. Security interoperability between these vendors is achieved using the IOR protocol. In our case the client and target EJB both happen to be deployed on the same vendor, but we still use IOR for propagating security details from the application client container to the EJB container. IORs are configured in vendor specific XML files rather than the standard ejb-jar.xml file. In the case of GlassFish, this is done within the <ior-security-config> element within the sun-ejb-jar.xml deployment descriptor file. We also need to specify the invoked EJB, BankServiceBean, in the deployment descriptor. An example of the sun-ejb-jar.xml deployment descriptor is shown below: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sun-ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD       Application Server 9.0 EJB 3.0//EN"       "http://www.sun.com/software/appserver/dtds/sun-ejb-jar_3_0-0.dtd"> <sun-ejb-jar>   <enterprise-beans>     <ejb>       <ejb-name>BankServiceBean</ejb-name>         <ior-security-config>           <as-context>              <auth-method>USERNAME_PASSWORD</auth-method>              <realm>default</realm>              <required>true</required>           </as-context>         </ior-security-config>     </ejb>   </enterprise-beans> </sun-ejb-jar> The as in <as-context> stands for the IOR authentication service. This specifies authentication mechanism details. The <auth-method> element specifies the authentication method. This is set to USERNAME_PASSWORD which is the only value for an application client. The <realm> element specifies the realm in which the client is authenticated. The <required> element specifies whether the above authentication method is required to be used for client authentication. When creating the corresponding EJB JAR file, the sun-ejb-jar.xml file should be included in the META-INF directory, as follows: <target name="package-ejb" depends="compile">     <jar jarfile="${build.dir}/BankService.jar">         <fileset dir="${build.dir}">              <include name="ejb30/session/**" />                           <include name="ejb30/entity/**" />               </fileset>               <metainf dir="${config.dir}">             <include name="persistence.xml" />                          <include name="sun-ejb-jar.xml" />         </metainf>     </jar> </target> As soon as we run the application client, GlassFish will prompt with a username and password form, as follows: If we reply with the username scott and password xyz the program will run. If we run the application with an invalid username or password we will get the following error message: javax.ejb.EJBException: nested exception is: java.rmi.AccessException: CORBA NO_PERMISSION 9998 ..... EJB Authorization Authorization, or access control, is the process of restricting operations to specific roles. In contrast with authentication, EJB authorization is completely application server independent. The EJB specification provides two kinds of authorization: declarative and programmatic. With declarative authorization all security checks are performed by the container. An EJB's security requirements are declared using annotations or deployment descriptors. With programmatic authorization security checks are hard-coded in the EJBs code using API calls. However, even with programmatic authorization the container is still responsible for authentication and for assigning roles to principals. Declarative Authorization As an example, consider the BankServiceBean stateless session bean with methods findCustomer(), addCustomer() and updateCustomer(): package ejb30.session; import javax.ejb.Stateless; import javax.persistence.EntityManager; import ejb30.entity.Customer; import javax.persistence.PersistenceContext; import javax.annotation.security.RolesAllowed; import javax.annotation.security.PermitAll; import java.util.*; @Stateless @RolesAllowed("bankemployee") public class BankServiceBean implements BankService { @PersistenceContext(unitName="BankService") private EntityManager em; private Customer cust; @PermitAll public Customer findCustomer(int custId) { return ((Customer) em.find(Customer.class, custId)); } public void addCustomer(int custId, String firstName, String lastName) { cust = new Customer(); cust.setId(custId); cust.setFirstName(firstName); cust.setLastName(lastName); em.persist(cust); } public void updateCustomer(Customer cust) { Customer mergedCust = em.merge(cust); } } We have prefixed the bean class with the annotation: @RolesAllowed("bankemployee") This specifies the roles allowed to access any of the bean's method. So only users belonging to the bankemployee role may access the addCustomer() and updateCustomer() methods. More than one role can be specified by means of a brace delineated list, as follows: @RolesAllowed({"bankemployee", "bankcustomer"}) We can also prefix a method with @RolesAllowed, in which case the method annotation will override the class annotation. The @PermitAll annotation allows unrestricted access to a method, overriding any class level @RolesAllowed annotation. As with EJB 3 in general, we can use deployment descriptors as alternatives to the @RolesAllowed and @PermitAll annotations. Denying Authorization Suppose we want to deny all users access to the BankServiceBean.updateCustomer() method. We can do this using the @DenyAll annotation: @DenyAll public void updateCustomer(Customer cust) { Customer mergedCust = em.merge(cust); } Of course if you have access to source code you could simply delete the method in question rather than using @DenyAll. However suppose you do not have access to the source code and have received the EJB from a third party. If you in turn do not want your clients accessing a given method then you would need to use the <exclude-list> element in the ejb-jar.xml deployment descriptor: <?xml version="1.0" encoding="UTF-8"?> <ejb-jar version="3.0"                         xsi_schemaLocation="http://java.sun.com/xml/ns/javaee             http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd"> <enterprise-beans> <session> <ejb-name>BankServiceBean</ejb-name> </session> </enterprise-beans> <assembly-descriptor> <exclude-list><method> <ejb-name>BankServiceBean</ejb-name> <method-name>updateCustomer</method-name></method></exclude-list> </assembly-descriptor> </ejb-jar> EJB Security Propagation Suppose a client with an associated role invokes, for example, EJB A. If EJB A then invokes, for example, EJB B then by default the client's role is propagated to EJB B. However, you can specify with the @RunAs annotation that all methods of an EJB execute under a specific role. For example, suppose the addCustomer() method in the BankServiceBean EJB invokes the addAuditMessage() method of the AuditServiceBean EJB: @Stateless @RolesAllowed("bankemployee") public class BankServiceBean implements BankService { private @EJB AuditService audit; ....      public void addCustomer(int custId, String firstName,                                                          String lastName) {              cust = new Customer();              cust.setId(custId);              cust.setFirstName(firstName);              cust.setLastName(lastName);              em.persist(cust);              audit.addAuditMessage(1, "customer add attempt");      }      ... } Note that only a client with an associated role of bankemployee can invoke addCustomer(). If we prefix the AuditServiceBean class declaration with @RunAs("bankauditor") then the container will run any method in AuditServiceBean as the bankauditor role, regardless of the role which invokes the method. Note that the @RunAs annotation is applied only at the class level, @RunAs cannot be applied at the method level. @Stateless @RunAs("bankauditor") public class AuditServiceBean implements AuditService { @PersistenceContext(unitName="BankService") private EntityManager em; @TransactionAttribute( TransactionAttributeType.REQUIRES_NEW) public void addAuditMessage (int auditId, String message) { Audit audit = new Audit(); audit.setId(auditId); audit.setMessage(message); em.persist(audit); } } Programmatic Authorization With programmatic authorization the bean rather than the container controls authorization. The javax.ejb.SessionContext object provides two methods which support programmatic authorization: getCallerPrincipal() and isCallerInRole(). The getCallerPrincipal() method returns a java.security.Principal object. This object represents the caller, or principal, invoking the EJB. We can then use the Principal.getName() method to obtain the name of the principal. We have done this in the addAccount() method of the BankServiceBean as follows: Principal cp = ctx.getCallerPrincipal(); System.out.println("getname:" + cp.getName()); The isCallerInRole() method checks whether the principal belongs to a given role. For example, the code fragment below checks if the principal belongs to the bankcustomer role. If the principal does not belong to the bankcustomer role, we only persist the account if the balance is less than 99. if (ctx.isCallerInRole("bankcustomer")) {     em.persist(ac); } else if (balance < 99) {            em.persist(ac);   } When using the isCallerInRole() method, we need to declare all the security role names used in the EJB code using the class level @DeclareRoles annotation: @DeclareRoles({"bankemployee", "bankcustomer"}) The code below shows the BankServiceBean EJB with all the programmatic authorization code described in this section: package ejb30.session; import javax.ejb.Stateless; import javax.persistence.EntityManager; import ejb30.entity.Account; import javax.persistence.PersistenceContext; import javax.annotation.security.RolesAllowed; import java.security.Principal; import javax.annotation.Resource; import javax.ejb.SessionContext; import javax.annotation.security.DeclareRoles; import java.util.*; @Stateless @DeclareRoles({"bankemployee", "bankcustomer"}) public class BankServiceBean implements BankService { @PersistenceContext(unitName="BankService") private EntityManager em; private Account ac; @Resource SessionContext ctx; @RolesAllowed({"bankemployee", "bankcustomer"}) public void addAccount(int accountId, double balance, String accountType) { ac = new Account(); ac.setId(accountId); ac.setBalance(balance); ac.setAccountType(accountType); Principal cp = ctx.getCallerPrincipal(); System.out.println("getname:" + cp.getName()); if (ctx.isCallerInRole("bankcustomer")) { em.persist(ac); } else if (balance < 99) { em.persist(ac); } } ..... } Where we have a choice declarative authorization is preferable to programmatic authorization. Declarative authorization avoids having to mix business code with security management code. We can change a bean's security policy by simply changing an annotation or deployment descriptor instead of modifying the logic of a business method. However, some security rules, such as the example above of only persisting an account within a balance limit, can only be handled by programmatic authorization. Declarative security is based only on the principal and the method being invoked, whereas programmatic security can take state into consideration. Because an EJB is typically invoked from the web-tier by a servlet, JSP page or JSF component, we will briefly mention Java EE web container security. The web-tier and EJB tier share the same security model. So the web-tier security model is based on the same concepts of principals, roles and realms.
Read more
  • 0
  • 0
  • 4478

article-image-zen-gift-education
Packt
23 Oct 2009
4 min read
Save for later

Zen Gift of Education

Packt
23 Oct 2009
4 min read
Zen Gift of Education Many distributions have special releases around Christmas and New Year. I was planning to look at some of these this month like last year's Ubuntu Christmas Edition. But instead I found a release that's useful enough to maintain all year around. ZenEdu is a Live distribution that packs a whole bunch of educational tools on top of the Slackware-based light-weight and zippy Zenwalk Linux. As per Zenwalk's Wiki, ZenEdu was initiated by a user on the distro's French forum last year in December. That time the distro contained mostly French-only educational programs. This year, several members of the Zenwalk Linux community decided to release an international edition of ZenEdu. The distro is a goldmine of open source educational software and also packs a detailed user manual, which shows the developers' serious approach to do things properly. The educational apps included in the distro cover a broad range of subjects. The ZenEdu ISO is about 700 MB and includes apps that'll help users with subjects like Astronomy, Mathematics, and Chemistry. Since learning is the core idea behind the distro, it goes beyond traditional curriculum subjects and also packs tools that'll teach students the basics of programming and music. Some of the tools I particularly like are Stellarium - the popular 3D planetarium, Stardict - a multi-language dictionary, ghemical - a comprehensive computational chemistry package, Little Wizard that introduces the basics of programming to young students, and Maxima, for the manipulation of symbolic and numerical expressions, including differentiation, integration, ordinary differential equations, systems of linear equations, etc. If you want to learn music, train your ears with Solfege, and use TuxGuitar to edit and play guitar tablatures. What sets ZenEdu apart from other educational distros is that it bundles other productivity tools as well. This includes general-purpose applications like the IceWeasel web browser, IceDove email client, Pidgin for instant messaging, Kompozer for authoring web pages, and OpenOffice.org for word processing. Furthermore, the distro packs several other apps, which according to the developers, were chosen based on their usefulness to students while keeping in mind the things that might interest them. This includes a simple program to manage personal tasks and todo lists, a drawing program, a comic book viewer, a video editor, and a program to create a wide array of 3D content. However, there are dozens of free software educational tools that aren't included in this CD due to size considerations. But that's no problem. Since ZenEdu is based on Zenwalk, it too can be expanded with drag-and-drop modules. To create a new customize ZenEdu Live CD, browse and download the modules of educational apps you want and use the remastering application, isomaster to add them to your customized ZenEdu Live CD! The highlight of this distro though is the iTALC tool for teachers. iTALC, which stands for Intelligent Teaching And Learning with Computers, is a powerful cross-platform didactical tool that lets teachers view and control other computers in their network. Using iTALC teachers can see what's going on in computer labs and take snapshots, remote-control computers to support and help students, run a demo on all students' computers in real-time, send text-messages to students, cycle power and rebooting computers remotely, etc. ZenEdu has a special 'teacher' account pre-configured to run iTALC. Once logged in from that user, you can start iTALC and navigate through its interface, first adding student computers, and then controlling or monitoring them. ZenEdu's wiki page advices that if you'll be using the program regularly, you should save the 'teacher' account's iTALC directory (/home/teacher/.italc/) inside zenlive/rootcopy of the Live CD via isomaster. This will load the iTALC configuration the next time you boot the remastered Live CD. If you'll be using iTALC regularly you'd be well off installing ZenEdu on to your hard disk. Unfortunately, ZenEdu isn't installable. It's only a Live CD, and at best can be installed onto a USB Flash stick for portability. Most of the specialized distros I've played with, tend to be too specialized. They do what they are supposed to, but nothing more. ZenEdu is different in that, in a single CD, the developers have managed to squeeze a good number of educational apps as well as everyday tools. I hope members of the Zenwalk community, actively develop and maintain ZenEdu.   Some more articles by Mayank Sharma: Meet the Distro guy Making a Complete yet Small Linux Distribution
Read more
  • 0
  • 0
  • 4908
article-image-configuring-and-securing-python-ldap-applications-part-2
Packt
23 Oct 2009
14 min read
Save for later

Configuring and securing PYTHON LDAP Applications Part 2

Packt
23 Oct 2009
14 min read
This is the second article in the article mini-series on Python LDAP applications by Matt Butcher. For first part please visit this link. In this article we will see some of the LDAP operations such as compare operation, search operation. We will also see how to change an LDAP password. The LDAP Compare Operation One of the simplest LDAP operations to perform is the compare operation. The LDAP compare operation takes a DN, an attribute name, and an attribute value and checks the directory to see if the given DN has an attribute with the given attribute name, and the given attribute value. If it returns true then there is a match, and if false then otherwise. The Python-LDAP API supports LDAP compare operations through the LDAPObject's compare() and compare_s() functions. The synchronous function is simple. It takes three string parameters (DN, attribute name, and asserted value), and returns 0 for false, and 1 for true: >>> dn = 'uid=matt,ou=users,dc=example,dc=com'>>> attr_name = 'sn'>>> attr_val = 'Butcher'>>> con.compare_s(dn, attr_name, attr_val)1 In this case, we check the DN uid=matt,ou=user,dc=example,dc=com to see if the surname (sn) has the value Butcher. It does, so the method returns 1. But let's set the attr_val to a different surname, one that the record does not contain: >>> attr_val = 'Smith'>>> con.compare_s(dn, attr_name, attr_val)0>>> Since the record identified by the DN uid=matt,ou=users,dc=example,dc=com does not have an SN attribute with the value Smith, this method returns 0, false. Historically, Python has treated the boolean value False with 0, and numeric values greater than zero as boolean True. So it is possible to use a compare like this: if con.compare_s(dn, attr_name, attr_val): print "Match"else: print "No match." If compare_s() returns 1, this will print Match. If it returns 0, it will print No match. Let's take a quick look, now, at the asynchronous version of the compare operation, compare(). As we saw in the section on binding, the asynchronous version starts the operation in a new thread, and then immediately returns control to the program, not waiting for the operation to complete. Later, the result of the operation can be examined using the LDAPObject's result() method. Running the compare() method is almost identical to the synchronized version, with the difference being the value returned: >>> retval = con.compare( dn, attr_name, attr_val )>>> print retval15 Here, we run a compare() method, storing the identification number for the returned information in the variable retval. Finding out the value of the returned information is a little trickier than one might guess. Any attempt to retrieve the result of a compare operation using the result() method will raise an exception. But, this is not a sign that the application has encountered an error. Instead, the exception itself indicates whether the compare operation returned true or false. For example, let's fetch the result for the previous operation in the way we might expect: >>> print con.result( retval )Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 405, in result res_type,res_data,res_msgid = self.result2(msgid,all,timeout) File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 409, in result2 res_type, res_data, res_msgid, srv_ctrls = self.result3 (msgid,all,timeout) File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 415, in result3 rtype, rdata, rmsgid, serverctrls = self._ldap_call (self._l.result3,msgid,all,timeout) File "/usr/lib/python2.5/site-packages/ldap/ldapobject.py", line 94, in _ldap_call result = func(*args,**kwargs)ldap.COMPARE_TRUE: {'info': '', 'desc': 'Compare True'} What is going on here? Attempting to retrieve the value resulted in an exception being thrown. As we can see from the last line, the exception raised was COMPARE_TRUE. Why? The developers of the Python-LDAP API worked around a difficulty in the standard LDAP C API by providing the results of the compare operation in the form of raised exceptions. Thus, the way to retrieve information from the asynchronous form of compare is with a try/except block: >>> retval = con.compare( dn, attr_name, attr_val )>>> try: ... con.result( retval )...... except ldap.COMPARE_TRUE:... print "Returned TRUE."...... except ldap.COMPARE_FALSE:... print "Returned FALSE."... Returned TRUE. In this example, we use the raised exception to determine whether the compare returned true, which raises the COMPARE_TRUE exception, or returned false, which raises COMPARE_FALSE. Performing compare operations is fairly straightforward, even with the nuances of the asynchronous version. The next operation we will examine is search. The Search Operation LDAP servers are intended as high read, low write databases, which means that it is expected that most operations that the server handles will be “read” operations that do not modify the contents of the directory information tree. And the main operation for reading a directory, as we have seen throughout this book, is the LDAP search operation. As a reminder, the LDAP search operation typically requires five parameters: The base DN, which indicates where in the directory information tree the search should start. The scope, which indicates how deeply the search should delve into the directory information tree. The search filter, which indicates which entries should be considered matches. The attribute list, which indicates which attributes of a matching record should be returned. A flag indicating whether attribute values should be returned (the Attrs Only flag). There are other additional parameters, such as time and size limits, and special client or server controls, but those are less frequently used. Once a search is processed, the server will return a bundle of information including the status of the search, all of the matching records (with the appropriate attributes), and, occasionally, error messages indicate some outstanding condition on the server. When writing Python-LDAP code to perform searches, we will need to handle all of these issues. In the Python-LDAP API, there are three (functional) variations of the search function: search() search_s() search_st() The first is the asynchronous form, and the second is the synchronous form. The third is a special form of the synchronous form that allows the programmer to add on a hard time limit in which the client must respond. There are two other versions of the search method, search_ext() and search_ext_s(). These two provide parameter placeholders for passing client and server extension mechanisms, but such extension handling is not yet functional, so neither of these functions is performatively different than the three above. We will begin by looking at the second method, search_s(). The search_s() function of the LDAPObject has two required parameters (Base DN and scope), and three optional parameters (search filter, attribute list, and the attrs only flag). Here, we will do a simple search for a list of surnames for all of the users in our directory information tree. For this, we will not need to set the attrs only flag (which is off by default, and, when turned on, will not return the attribute values). But we will need the other four parameters: Base DN: The users branch, ou=users,dc=example,dc=com Scope: Subtree (ldap.SCOPE_SUBTREE) Filter: Any person objects, (objectclass=person) Attributes: Surname (sn) Now we can perform our search in the Python interpreter: >>> import ldap>>> dn = "uid=matt,ou=users,dc=example,dc=com">>> pw = "secret">>> >>> con = ldap.initialize('ldap://localhost')>>> con.simple_bind_s( dn, pw )(97, [])>>>>>> base_dn = 'ou=users,dc=example,dc=com'>>> filter = '(objectclass=person)'>>> attrs = ['sn']>>> >>> con.search_s( base_dn, ldap.SCOPE_SUBTREE, filter, attrs )[('uid=matt,ou=Users,dc=example,dc=com', {'sn': ['Butcher']}),('uid=barbara,ou=Users,dc=example,dc=com', {'sn': ['Jensen']}),('uid=adam,ou=Users,dc=example,dc=com', {'sn': ['Smith']}),('uid=dave,ou=Users,dc=example,dc=com', {'sn': ['Hume']}),('uid=manny,ou=Users,dc=example,dc=com', {'sn': ['Kant']}),('uid=cicero,ou=Users,dc=example,dc=com', {'sn': ['Tullius']}),('uid=mary,ou=Users,dc=example,dc=com', {'sn': ['Wollstonecraft']}),('uid=thomas,ou=Users,dc=example,dc=com', {'sn': ['Hobbes']})]>>> The first seven lines should look familiar – there is nothing in these lines not covered in the previous sections. Next, we declare variables for the Base DN (base_dn), filter (filter), and attributes (attrs). While base_dn and filter are strings, attrs requires a list. In our case, it is a list with one member: ['sn']. Safe FiltersIf you are generating the LDAP filter dynamically (or letting users specify the filter), then you may want to use the escape_filter_chars() and filter_format() functions in the ldap.filter module to keep your filter strings safely escaped. We don't need to create a variable for the scope, since all of the available scopes (subtree, base, and onelevel) are available as constants in the ldap module: ldap.SCOPE_SUBTREE, ldap.SCOPE_BASE, and ldap.SCOPE_ONELEVEL. The line highlighted above shows the search, and the lines following – that big long messy conglomeration of tuples, dicts, and lists – is the result returned from the server. Strictly speaking, the result returned from search_s() is a list of tuples, where each tuple contains a DN string, and a dict of attributes. Each dict of attributes has a string key (the attribute name), and a list of string values. While this data structure is compact, it is not particularly easy to work with. For a complex data structure like this, it can be useful to create some wrapper objects to make use of this information a little more intuitive. The ldaphelper Helper Module To better work with LDAP results, we will create a simple package with just one class. This will be our ldaphelper module, stored in ldaphelper.py: import ldiffrom StringIO import StringIOfrom ldap.cidict import cidictdef get_search_results(results): """Given a set of results, return a list of LDAPSearchResult objects. """ res = [] if type(results) == tuple and len(results) == 2 : (code, arr) = results elif type(results) == list: arr = results if len(results) == 0: return res for item in arr: res.append( LDAPSearchResult(item) ) return resclass LDAPSearchResult: """A class to model LDAP results. """ dn = '' def __init__(self, entry_tuple): """Create a new LDAPSearchResult object.""" (dn, attrs) = entry_tuple if dn: self.dn = dn else: return self.attrs = cidict(attrs) def get_attributes(self): """Get a dictionary of all attributes. get_attributes()->{'name1':['value1','value2',...], 'name2: [value1...]} """ return self.attrs def set_attributes(self, attr_dict): """Set the list of attributes for this record. The format of the dictionary should be string key, list of string alues. e.g. {'cn': ['M Butcher','Matt Butcher']} set_attributes(attr_dictionary) """ self.attrs = cidict(attr_dict) def has_attribute(self, attr_name): """Returns true if there is an attribute by this name in the record. has_attribute(string attr_name)->boolean """ return self.attrs.has_key( attr_name ) def get_attr_values(self, key): """Get a list of attribute values. get_attr_values(string key)->['value1','value2'] """ return self.attrs[key] def get_attr_names(self): """Get a list of attribute names. get_attr_names()->['name1','name2',...] """ return self.attrs.keys() def get_dn(self): """Get the DN string for the record. get_dn()->string dn """ return self.dn def pretty_print(self): """Create a nice string representation of this object. pretty_print()->string """ str = "DN: " + self.dn + "n" for a, v_list in self.attrs.iteritems(): str = str + "Name: " + a + "n" for v in v_list: str = str + " Value: " + v + "n" str = str + "========" return str def to_ldif(self): """Get an LDIF representation of this record. to_ldif()->string """ out = StringIO() ldif_out = ldif.LDIFWriter(out) ldif_out.unparse(self.dn, self.attrs) return out.getvalue() This is a large chunk of code to take in at once, but the function of it is easy to describe. Remember, to use a Python module, you must make sure that the module is in the interpreter's path. See the official Python documentation (http://python.org) for more information. The package has two main components: the get_search_results() function, and the LDAPSearchResult class. The get_search_results() function simply takes the results from a search (either the synchronous ones, or the results from an asynchronous one, fetched with result()) and converts the results to a list of LDAPSearchResult objects. An LDAPSearchResults object provides some convenience methods for getting information about a record. The get_dn() method returns the record's DN, and the following methods all provide access to the attributes or the record: get_dn(): return the string DN for this record. get_attributes(): get a dictionary of all of the attributes. The keys  are attribute name strings, and the values are lists of attribute value  strings. set_attributes(): takes a dictionary with attribute names for keys, and  lists of attribute values for the value field. has_attribute(): takes a string attribute name and returns true if that attribute name is in the dict  of attributes returned. get_attr_values(): given an attribute name, this returns all of the  values for that attribute (or none if that attribute does not exist). get_attr_names(): returns a list of all of the attribute names for this  record. pretty_print(): returns a formatted string presentation of the record. to_ldif(): returns an LDIF formatted representation of the record. This object doesn't add much to the original returned data. It just makes it a little easier to access. Attribute NamesLDAP attributes can have multiple names. The attribute for surnames has two names: surname and sn (though most LDAP directory entries use sn). Either one might be returned by the server. To make your application aware of this difference, you can use the ldap.schema package to get schema information. The Case Sensitivity Gotcha There is one noteworthy detail in the code above. The search operation returns the attributes in a dictionary. The Python dictionary is case sensitive; the key TEST is different than the key test. This exemplifies a minor problem in dealing with LDAP information. Standards-compliant LDAP implementations treat some information in a case-insensitive way. The following items are, as a rule, treated as case-insensitive: Object class names: inetorgperson is treated as being the same as inetOrgPerson. Attribute Names: givenName is treated as being the same as givenname. Distinguished Names: DNs are case-insensitive, though the all-lower-case version of a DN is called  Normalized Form. The main area where this problem surfaces is in retrieving information from a search. Since the attributes are returned in a dict, they are, by default, treated as case-sensitive. For example, attrs.has_key('objectclass') will return False if the object class attribute name is spelled objectClass. To resolve this problem, the Python-LDAP developers created a case-insensitive dictionary implementation (ldap.cidict.cidict). This cidict class is used above to wrap the returned attribute dictionary. Make sure you do something similar in your own code, or you may end up with false misses when you look for attributes in a case-sensitive way, e.g. when you look for givenName in an entry where the attribute name is in the form givenname.
Read more
  • 0
  • 1
  • 18229

article-image-tapestry-5-advanced-components
Packt
23 Oct 2009
10 min read
Save for later

Tapestry 5 Advanced Components

Packt
23 Oct 2009
10 min read
Following are some of the components, we'll examine in Tapestry 5: The Grid component allows us to display different data in a fairly sophisticated table. We are going to use it to display our collection of celebrities. The BeanEditForm component greatly simplifies creating forms for accepting user input. We shall use it for adding a new celebrity to our collection. The DateField component provides an easy and attractive way to enter or edit the date. The FCKEditor component is a rich text editor, and it is as easy to incorporate into a Tapestry 5 web application, just as a basic TextField is. This is a third party component, and the main point here is to show that using a library of custom components in a Tapestry 5 application requires no extra effort. It is likely that a similar core component will appear in a future version of the framework. Grid Component It is possible to display our collection of celebrities with the help of the Loop component. It isn't difficult, and in many cases, that will be exactly the solution you need for the task at hand. But, as the number of displayed items grow (our collection grows) different problems may arise. We might not want to display the whole collection on one page, so we'll need some kind of pagination mechanism and some controls to enable navigation from page to page. Also, it would be convenient to be able to sort celebrities by first name, last name, occupation, and so on. All this can be achieved by adding more controls and more code to finally achieve the result that we want, but a table with pagination and sorted columns is a very common part of a user interface, and recreating it each time wouldn't be efficient. Thankfully, the Grid component brings with it plenty of ready to use functionality, and it is very easy to deal with. Open the ShowAll.tml template in an IDE of your choice and remove the Loop component and all its content, together with the surrounding table: <table width="100%"> <tr t_type="loop" t_source="allCelebrities" t:value="celebrity"> <td> <a href="#" t_type="PageLink" t_page="Details" t:context="celebrity.id"> ${celebrity.lastName} </a> </td> <td>${celebrity.firstName}</td> <td> <t:output t_format="dateFormat" t:value="celebrity.dateOfBirth"/> </td> <td>${celebrity.occupation}</td> </tr> </table> In place of this code, add the following line: <t:grid t_source="allCelebrities"/> Run the application, log in to be able to view the collection, and you should see the following result: Quite an impressive result for a single short line of code, isn't it? Not only are our celebrities now displayed in a neatly formatted table, but also, we can sort the collection by clicking on the columns' headers. Also note that occupation now has only the first character capitalized—much better than the fully capitalized version we had before. Here, we see the results of some clever guesses on Tapestry's side. The only required parameter of the Grid component is source, the same as the required parameter of the Loop component. Through this parameter, Grid receives a number of objects of the same class. It takes the first object of this collection and finds out its properties. It tries to create a column for each property, transforming the property's name for the column's header (for example, lastName property name gives Last Name column header) and makes some additional sensible adjustments like changing the case of the occupation property values in our example. All this is quite impressive, but the table, as it is displayed now, has a number of deficiencies: All celebrities are displayed on one page, while we wanted to see how pagination works. This is because the default number of records per page for  Grid component is 25—more than we have in our collection at the moment. The last name of the celebrities does not provide a link to the Details page anymore. It doesn't make sense to show the Id column. The order of the columns is wrong. It would be more sensible to have the Last Name in the first column, then First Name, and finally the Date of Birth. By default, to define the display of the order of columns in the table, Tapestry will use the order in which getter methods are defined in the displayed class. In the Celebrity class, the getFirstName method is the first of the getters and so the First Name column will go first, and so on. There are also some other issues we might want to take care of, but let's first deal with these four. Tweaking the Grid First of all let's change the number of records per page. Just add the following parameter to the component's declaration: <t:grid t_source="allCelebrities" rowsPerPage="5"/> Run the application, and here is what you should see: You can now easily page through the records using the attractive pager control that appeared at the bottom of the table. If you would rather have the pager at the top, add another parameter to the Grid declaration: <t:grid t_source="allCelebrities" rowsPerPage="5" pagerPosition="top"/> You can even have two pagers, at the top and at the bottom, by specifying pagerPosition="both", or no pagers at all (pagerPosition="none"). In the latter case however, you will have to provide some custom way of paging through records. The next enhancement will be a link surrounding the celebrity's last name and linking to the Details page. We'll be adding an ActionLink and will need to know which Celebrity to link to, so we have the Grid store using the row parameter. This is how the Grid declaration will look: <t:grid t_source="allCelebrities" rowsPerPage="5" row="celebrity"/> As for the page class, we already have the celebrity property in it. It should have been left from our experiments with the Loop component. It will also be used in exactly the same way as with Loop, while iterating through the objects provided by its source parameter, Grid will assign the object that is used to display the current row to the celebrity property. The next thing to do is to tell Tapestry that when it comes to the contents of the Last Name column, we do not want Grid to display it in a default way. Instead, we shall provide our own way of displaying the cells of the table that contain the last name. Here is how we do this: <t:grid t_source="allCelebrities" rowsPerPage="5" row="celebrity"> <t:parameter name="lastNameCell"> <t:pagelink t_page="details" t_context="celebrity.id"> ${celebrity.lastName} </t:pagelink> </t:parameter> </t:grid> Here, the Grid component contains a special Tapestry element , similar to the one that we used in the previous chapter, inside the If component. As before, it serves to provide an alternative content to display, in this case, the content which will fill in the cells of the Last Name column. How does Tapestry know this? By the name of the element, lastNameCell. The first part of this name, lastName, is the name of one of the properties of the displayed objects. The last part, Cell, tells Tapestry that it is about the content of the table cells displaying the specified property. Finally, inside , you can see an expansion displaying the name of the current celebrity and surrounding it with the PageLink component that has for its context the ID of the current celebrity. Run the application, and you should see that we have achieved what we wanted: Click on the last name of a celebrity, and you should see the Details page with the appropriate details on it. All that is left now is to remove the unwanted Id column and to change the order of the remaining columns. For this, we'll use two properties of the Grid—remove and reorder. Modify the component's definition in the page template to look like this: <t:grid t_source="celebritySource" rowsPerPage="5" row="celebrity" remove="id" reorder="lastName,firstName,occupation,dateOfBirth"> <t:parameter name="lastNameCell"> <t:pagelink t_page="details" t_context="celebrity.id"> ${celebrity.lastName} </t:pagelink> </t:parameter> </t:grid> Please note that re-ordering doesn't delete columns. If you omit some columns while specifying their order, they will simply end up last in the table. Now, if you run the application, you should see that the table with a collection of celebrities is displayed exactly as we wanted: Changing the Column Titles Column titles are currently generated by Tapestry automatically. What if we want to have different titles? Say we want to have the title, Birth Date, instead of Date Of Birth. The easiest and the most efficient way to do this is to use the message catalog, the same one that we used while working with the Select component in the previous chapter. Add the following line to the app.properties file: dateOfBirth-label=Birth Date Run the application, and you will see that the column title has changed appropriately. This way, appending -label to the name of the property displayed by the column, you can create the key for a message catalog entry, and thus change the title of any column. Now you should be able to adjust the Grid component to most of the possible requirements and to display with its help many different kinds of objects. However, one scenario can still raise a problem. Add an output statement to the getAllCelebrities method in the ShowAll page class, like this: public List<Celebrity> getAllCelebrities() { System.out.println("Getting all celebrities..."); return dataSource.getAllCelebrities(); } The purpose of this is simply to be aware when the method is called. Run the application, log in, and as soon as the table with celebrities is shown, you will see the output, as follows: Getting all celebrities... The Grid component has the allCelebrities property defined as its source, so it invokes the getAllCelebrities method to obtain the content to display. Note however that Grid, after invoking this method, receives a list containing all 15 celebrities in collection, but displays only the first five. Click on the pager to view the second page—the same output will appear again. Grid requested for the whole collection again, and this time displayed only the second portion of five celebrities from it. Whenever we view another page, the whole collection is requested from the data source, but only one page of data is displayed. This is not too efficient but works for our purpose. Imagine, however, that our collection contains as many as 10,000 celebrities, and it's stored in a remote database. Requesting for the whole collection would put a lot of strain on our resources, especially if we are going to have 2,000 pages. We need to have the ability to request the celebrities, page-by-page—only the first five for the first page, only the second five for the second page and so on. This ability is supported by Tapestry. All we need to do is to provide an implementation of the GridDataSource interface. Here is a somewhat simplified example of such an implementation.
Read more
  • 0
  • 0
  • 3096

article-image-using-data-pager-control-visual-studio-2008
Packt
23 Oct 2009
5 min read
Save for later

Using the Data Pager Control in Visual Studio 2008

Packt
23 Oct 2009
5 min read
A direct connection to SQL Server 2008 is not possible with this version of SQL Server and Visual Studio 2008. One way to get around this is to use an ODBC connection to the SQL Server and then using the ODBC connection to retrieve the data. Another way described is to use the OLEDB connectivity option shown in this article. Article Overview We first create an ASP.NET Web Application project. To the default.aspx page we add a ListView control. Then we configure the ListView Control by configuring its data source and its displayed features. At this point a DataPager can be included as part of the ListView, but adding a DataPager manually is also shown. Controlling the number of displayed items in a page can be carried out using page load event code or declaratively. Creating an ASP.NET Web Application From the File menu item create a new project that opens up the window shown in the next figure. Make sure you are creating a .NET Framework 3.5 ASP.NET Web application project (use drop-down at top right of this window). The default name of the application has been changed to DataPager as shown. Click on the OK button to create the project. The project is created with all the necessary files and the template for the Default.aspx page as shown. The Solution Explorer and the Class View of the project has all the information on this project. The Split tab at the bottom of the 'Default.aspx' shows both the Design page as well as the HTML code for the page. Adding a ListView Control and connecting to a Data Source Drag and drop a ListView Control from the Toolbox on to the design page between the <div/> tags as shown. The Code is automatically generated as shown in the next figure. The ListView instance has a Id property "ListView1". Now you can configure the ListView using the Smart Tasks handle - the small arrow head [>] attached to the list view at the top right. Click the Smart Task handle to open the list of tasks to be performed as shown. The only task you find here is the "Choosing the data source". Configuring the Data Source Now click on <New data source...>. This opens the Data Source Configuration Wizard. Click on Database icon which sets the stage for bringing data from SQL Server with an Id property "SQLDataSource1". This supports connecting to any ADO.NET datasource. Click on the OK button in the above window. This opens the window where you need to choose the "Connection String", a very important item for connecting to a source of data.     Click on the <New Connection...> button. This opens the Add Connection window with the default options displayed. Click on the Change... button since we are interested in connecting to SQL Server 2008. Click on the <other> drop-down menu item and choose the .NET Framework Data Provider for OLEDB as shown. Click on the OK button. This brings you back to the Add Connection window and you need to indicate the DataLinks. Click on the OLEDB Providers drop-down and choose Microsoft OLEDB Provider for SQL server as shown. Click on the Data Links... button. This brings up the Data Link Properties window as shown. Choose the Windows authentication. If you click on the drop-down handle for Selecting the databases on the server a list of databases will be displayed. Choose the pubsx database. Click on the OK on the Data Link properties page which will take you back to the Add Connection window updating all the information. You may test and verify the connection on this page as well. Click on the OK button on the Add Connection window. This will take you back to the Configure Data Source window seen earlier after updating the connection string as shown. Click on the Next button. The window that shows up is about saving the connection information to the web.config file. Make sure you read the notes on this window. Click on the Next button. In the window that gets displayed you can choose either a table from the database, or provide a SQL statement, or the name of a stored procedure. Here to keep it simple, the authors table is chosen from the drop-down list. You can make use of other buttons on this window to refine your select statement. Here just the table name is chosen. From the columns that are displayed a few columns are chosen. Click on the Next button. This displays the window where you can test your query. It comes up blank, but when you hit the button Test Query, the blank area gets populated by the result returned by the query as shown. Now click on the Finish button. This closes this window and the details of the just finished data source gets into the designer interface as shown.  
Read more
  • 0
  • 0
  • 2590
article-image-introduction-re-host-based-modernization-using-tuxedo
Packt
23 Oct 2009
19 min read
Save for later

Introduction to Re-Host based Modernization Using Tuxedo

Packt
23 Oct 2009
19 min read
Introduction SOA enablement wraps key application interfaces in services, and integrates it into the SOA. This largely leaves the existing application logic intact, minimizing changes and adding risk only to those components that needed restructuring work to become SOA-ready. While the interfaces are modernized, without subjecting the core application components to a lot of change, the high costs and the various legacy risks associated with the mainframe platform remain. In addition, the performance and scalability of the new interfaces needs to be well-specified and tested, and the additional load they place on the system should be included in any planned capacity upgrades, potentially increasing the overall costs. Reducing or eliminating the legacy mainframe costs and risks via re-host based modernization also helps customers to fund SOA enablement, and the re-architecture phases of legacy modernization, and lay the groundwork for these steps. SOA-enabling a re-hosted application is a much easier process on an open-systems-based, SOA-ready software stack, and a more efficient one as well in terms of system resource utilization and cost. Re-architecting selected components of a re-hosted application based on specific business needs is a lower risk approach than re-architecting the entire applications en masse, and the risk can be further reduced by ensuring that target re-hosting stack provides rugged and transparent integration between re-hosted services and new components. Keeping It Real: Selective re-architecture is all about maximizing ROI by focusing re-architecture investment in the areas with the best pay-off. Undertaking a change from one language or development paradigm to another shouldn't be undertaken lightly—the investment and risks need to be well understood and justified. It is the right investment for components that require frequent maintenance changes but are difficult to maintain, because of poor /structure and layered changes. The payback on re-architecture investment will come from reducing the cost of future maintenance. Similarly, components that need significant functional changes to meet new business requirements can benefit from substantial productivity increase after re-architecture to a more modern development framework with richer tools to support future changes. The payback comes from greater business agility and time-to-market improvements. On the other hand, well-structured and maintainable COBOL components that do not need extensive changes to meet business needs will have very little return to show for the significant re-architecture investment. Leaving them in COBOL on a modern, extensible platform saves significant re-architecture costs that can be invested elsewhere, reduces risk, and shortens payback time. These considerations can help to optimize ROI for medium to large modernization projects where components measure in hundreds or thousands and contain millions or tens of millions lines of code. Re-Hosting Based Modernization For many organizations, mainframe modernization has become a matter of 'how', and not 'if'. Numerous enterprises and public sector organizations choose re-hosting as the first tangible step in their legacy modernization program precisely because it delivers the best ROI in the fastest possible manner, and accelerates the move to SOA enablement and selective re-architecture. Oracle together with our services partners provides a comprehensive re-hosting-based modernization solution that many customers have leveraged for a successful migration of selected applications or complete mainframe environments ranging from a few hundred MIPS to well over 10,000 MIPS. Two key pillars support successful re-hosting projects: Optimal target environment that lowers the Total Cost of Ownership (TCO) by 50–80 percent and maintains mainframe-class Quality of Service (QoS) using open, extensible, SOA-ready, future-proof architecture Predictable, efficient projects delivered by our SI partners with proven methodologies and automated tools Optimal target environment provided by Oracle is powered by proven open systems software stack leveraging Oracle Database and Oracle Tuxedo for a rock-solid, mainframe-class transaction processing (TP) infrastructure closely matching mainframe requirements for online applications. Mainframe-compatible Transaction Processing: Support for IBM CICS or IMS TM applications in native COBOL or C/C++ language containers with mainframe-compatible TP features. RASP: Mainframe-class performance, reliability, and scalability provided by Oracle Real Application Clusters (RAC) and Tuxedo multi-node and multi-domain clustering for load-balancing and high availability despite failure of individual nodes or network links. Workload and System Management: End-to-end transaction and service monitoring to support 24X7 operations management provided by Oracle's Enterprise Manager Grid Control and Tuxedo System and Application Monitor. SOA Enablement and Integration: Extensibility with Web services using Oracle Services Architecture Leveraging Tuxedo (SALT), J2EE integration (using WebLogic-Tuxedo Connector (WTC), Enterprise Service Bus (ESB), Portal, and BPM technologies to enable easy integration of re-hosted applications into modern Service-Oriented Architectures (SOAs). Scalable Platforms and Commodity Hardware: Scalable, Linux/UNIX-based open systems from HP, Dell, Sun, and IBM, providing: Performance on a par with mainframe systems for most workloads at significantly reduced TCO Reliability and workload management similar to mainframe installations, including physical and logical partitioning Robust clustering technologies for high availability and fail-over capabilities within a data center or across the world The diagram below shows conceptual mapping of mainframe environment to compatible open systems infrastructure: Predictable, efficient projects delivered by leading SIs and key modernization specialists use risk-mitigation methodologies, and automated tools honed over numerous projects to address a complete range of Online, Batch, and Data architectures, and the various technologies used in them. These project methodologies and automated tools that support them encompass all phases of a migration project: Preliminary Assessment Study Application Asset Discovery and Analysis Application and Data Conversion (pilot or entire application portfolio) System and Application Integration Test Engineering Regression and Performance Testing Education and Training Operations Migration Switch-Over Combining a proven target architecture stack that is well-matched to the needs of mainframe applications with mature methodologies supported by automated tools has led to a large and growing number of successful re-hosting projects. There is a rising interest to leverage the re-hosting approach to mainframe application modernization, as a way to get off a mainframe fast, and with minimal risk, in a more predictable manner for large, business-critical applications evolved over a long term and multiple development teams. Re-hosting based modernization approach preserves an organizations long term investment in critical business logic and data without risking business operations or sacrificing the QoS, while enabling customers to: Reduce or eliminate mainframe maintenance costs, and/or defer upgrade costs, saving customers 50–80 percent of their annual maintenance and operations budget Increase productivity and flexibility in IT development and operations, protecting long-term investment through application modernization Speed up and simplify application integration via SOA, without losing transactional integrity and the high performance expected by the users The rest of this article explores the critical success factors and proven transformation architecture for re-hosting legacy applications and data, describes SOA integration options and considerations when SOA-enabling re-hosted applications, highlights key risk mitigation methodologies, and provides a foundation for the financial analysis and ROI model derived from over a hundred, mainframe re-hosting projects. Critical Success Factors in Mainframe Re-Hosting Companies considering a re-hosting-based modernization strategy that involves migrating some applications off the mainframe have to address a range of concerns, which can be summarized by the following questions: How to preserve the business logic of these applications and their valuable data? How to ensure that migrated applications continue to meet performance requirements? How to maintain scalability, reliability, transactional integrity, and other QoS attributes in an open system environment? How to migrate in phases, maintaining robust integration links between migrated and mainframe applications? How to achieve predictable, cost-effective results and ensure a low-risk project? Meeting these challenges requires a versatile and powerful application infrastructure—one that natively supports key mainframe languages and services, enables automated adaptation of application code, and delivers proven, mainframe-like QoS on open system platforms. For re-hosting to enable broader aspects of the modernization strategy, this infrastructure must also provide native Web services and ESB capabilities to rapidly integrate re-hosted applications as first-class services in an SOA. Equally important is a proven, risk-mitigation methodology, automated tools, and project services specifically honed to address automated conversion and adaptation of application code and data, supported by cross-platform test engineering and execution methodology, strong system and application integration expertise, and deep experience with operations migration and switch-over. Preserving Application Logic and Data The re-hosting approach depends on a mainframe-compatible transaction processing and application services platform supporting common mainframe languages such as COBOL and C, which preserves the original business logic and data for the majority of mainframe applications and avoids the risks and uncertainties of a re-write. A complete re-hosting solution provides native support for TP and Batch programs, leveraging an application server-based platform that provides container-based support for COBOL and C/C++ application services, and TP APIs similar to IBM CICS, IMS TM, or other mainframe TP monitors. Online Transaction Processing Environment Oracle Tuxedo is the most popular TP platform for open systems, as well as leading re-hosting platform that can run most of mainframe COBOL and C applications unchanged in container-based framework that combines common application server features, including health monitoring, fail-over, service virtualization, and dynamic load balancing critical to large-scale OLTP applications together with standard TP features, including transaction management and reliable coordination of distributed transactions (a.k.a. Two-Phase Commit or XA standard). It provides the highest possible performance and scalability, and has been recently benchmarked against a mainframe at over 100,000 transactions per second, with sub-second response time. Oracle Tuxedo supports common mainframe programming languages, that is, COBOL and C, and provides comprehensive TP features compatible with CICS and IMS TM, which makes it a preferred application platform choice for re-hosting CICS or IMS TM applications with minimal changes and risks. In the Tuxedo environment, COBOL or C business logic remains unchanged. The only adaptation required is automated mapping of CICS APIs (CICS EXEC calls) to equivalent Tuxedo API functions. This mapping typically leverages a pre-processor and a mapping library implemented on Tuxedo platform, and using a full range of Tuxedo APIs. The automated nature of pre-processing and comprehensive coverage provided by the library ensures that most CICS COBOL or C programs are easily transformed into Tuxedo services. Unlike other solutions that embed this transformation in their compiler coupled with a proprietary emulation run-time, Tuxedo-based solution provides this mapping as a compiler-independent source module, which can be easily extended as needed. The resultant code uses Tuxedo API at native speed, allowing it to reach tens of thousands of transactions per second, while taking advantage of all Tuxedo facilities. In a re-hosted application CICS transactions become Tuxedo services, registered for processing by Tuxedo server processes. These services can be deployed in a single machine or across multiple machines in a Tuxedo domain (SYSPLEX-like cluster.). The services are called by front-end Java, .Net, or Tuxedo/WS clients, or UI components (tn3270 or web-based converted 3270/BMS screens), or by other services in case of transaction linking. Deferred transactions are handled by Tuxedo's/Q component, which provides in-memory and persistent queuing services. The diagram below shows Oracle Tuxedo and its surrounding ecosystem of SOA, J2EE, ESB, CORBA, MQ, and Mainframe integration components:   User Interface Migration The UI elements in these programs are typically defined using CICS Basic Mapping Support (BMS) for 3270 "green screen" terminals. While it is possible to preserve these using tn3270 emulation, many customers in re-hosting projects choose to take advantage of automated conversion of BMS macros into JSP/HTML for Web UI. Supported by a specialized Javascript library, these Web screens mimic the appearance and the behavior of "green screens" in a web browser, including tab-based navigation and PF keys. These UI components can connect to re-hosted CICS transactions running as Tuxedo services using Oracle Jolt (Java client interface for Tuxedo), Weblogic-Tuxedo Connector (WTC), or Tuxedo's Web services gateway provided by Oracle Services Architecture Leveraging Tuxedo (SALT) product. The diagram on the next page depicts a target re-hosting architecture for a typical mainframe OLTP application. The architecture uses Tuxedo services to run re-hosted CICS programs and a web application server to run re-hosted BMS UI. The servlets or JSPs containing the HTML that defines the screens, connect with Tuxedo services via Oracle Jolt, WTC, or SALT. Customers using mainframe 4GLs or languages such as PL/I or Assembler frequently choose to convert these applications to COBOL or C/C++. The adaptation of CICS or IMS TM API calls is automated through a mapping layer, which minimizes overall changes for the development team and allows them to maintain the familiar applications. For more significant extensions and new capabilities, customers incrementally leverage Tuxedo's own APIs and facilities, or leverage a tightly-linked J2EE environment provided by the WebLogic Server, and even transparently make Web services calls. The optimal extensibility options depend on application needs, availability of Java or C/COBOL skills, and other factors.   Feature or Action CICS Verb Tuxedo API Communications Area DFHCOMMAREA Typed Buffer Transaction Request LINK tpcall Transaction Return RETURN tpreturn Transfer Control XCTL tpforward Allocate Storage GETMAIN tpalloc Queues READQ / WRITEQ TD,TS /Q tpenqueue / tpdequeue Begin new transaction START TRANID /Q and TMQFORWARD Abort transaction ISSUE ABEND tpreturn TPFAIL Commit or Rollback SYNCPOINT / SYNCPOINT ROLLBACK tpcommit / tpabort     Keeping it Real:For those familiar with CICS, this is a very short example of the CICS verbs. CICS has many functions, most of which either map natively to a similar Tuxedo API or are provided by migration specialists based on their extensive experience with such migrations. In summary, Tuxedo provides a popular platform for deploying, executing, and managing COBOL and C re-hosted transactional applications requiring any of the following OLTP and infrastructure services: Native, compiler-independent support for COBOL, C, or C++ Rich set of infrastructure services for managing and scaling diverse workloads Feature-set compatibility and inter-operability with IBM CICS and IMS/TM Two-Phase Commit (2PC) for managing transactions across multiple application domains and XA-compliant resource managers (databases, message queues) Guaranteed inter-application messaging and transactional queuing Transactional data access (using XA-compliant resource managers) with ACID qualities Services virtualization and dynamic load balancing Centralized management of multiple nodes in a domain, and across multiple domains Communications gateways for multiple traditional and modern communication protocols SOA Enablement through native Web services and ESB integration Workload Monitoring and Management An important aspect of the mainframe environment is workload monitoring and management, which provides information for effective performance analysis and capabilities that enable mainframe systems to achieve better throughput and responsiveness. Oracle's Tuxedo System and Application Monitor (TSAM) provides similar capabilities too. Define monitoring policies and patterns based on application requests, services, system servers such as gateways, bridges, and XA-defined stages of a distributed transaction Define SLA thresholds that can trigger a variety of events within Tuxedo event services including notifications, and instantiation of additional servers Monitor transactions on an end-to-end basis from a client call through all services across all domains involved in a client request Collect service statistics for all infrastructure components such as servers and gateways Detail time spent on IPC queues, waiting on network links, and time spent on subordinate services TSAM provides a built-in, central, web-based management and monitoring console, and an open framework for integration with third-party performance management tools. Batch Jobs Mainframe batch jobs are a response to a human 24-hour clock on which many businesses run. It includes beginning-of-period or end-of-period (day, week, month, quarter) processing for batched updates, reconciliation, reporting, statement generation, and similar applications. In some industries, external events tied to a fixed schedule such as intra-day, opening or closing trade in a stock exchange, drive specific processing needs. Batch applications are an equally important asset, and often need to be preserved and migrated as well. The batch environment uses Job Control Language (JCL) jobs managed and monitored by JES2 or JES3 (Job Entry System), which invoke one or more programs, access and manipulate large datasets and databases using sort and other specialized utilities, and often run under the control of a job scheduler such as CA-7/CA-11. JCL defines a series of job steps—a sequence of programs and utilities, specifies input and output files, and provides exception handling. Automated parsing and translation of JCL jobs to UNIX scripts such as Korn shell (ksh) or Perl, enables the overall structure of the job to remain the same, including job steps, classes, and exception handling. Standard shell processing is supplemented with required utilities such as SyncSort, and support for Generation Data Group (GDG) files. REXX/CLIST/PROC scripting environments on the mainframe are similarly converted to ksh or other scripting languages. Integration with Oracle Scheduler, or other job schedulers running in UNIX/Linux or Windows provides a rich set of calendar and event-based scheduling capabilities as well as dependency management similar to mainframe schedulers. In some cases, reporting done via batch jobs can be replaced using standard reporting packages such as Oracle BI Publisher. The diagram below shows a typical target re-hosting architecture for batch. It includes a scheduler to control and trigger batch jobs, scripting framework to support individual job scripts, and an application server execution framework for the batch COBOL or C programs. Unlike other solutions that run these programs directly as OS processes without the benefit of application server middleware, Oracle recommends using container-based middleware to provide higher reliability, availability, and monitoring to the batch programs. The target batch programs invoked by the scripts can also run directly as OS processes, but if mainframe-class management and monitoring similar to JES2 or JES3 environment is a requirement, these programs can run as services under Tuxedo, benefiting from the health monitoring, fail-over, load balancing, and other application server-like features it provides. Files and Databases When moving platforms (mainframe to open systems), the application and data have to be moved together. Data schemas and data stores need to be moved in a re-hosted mainframe modernization project just as with a re-architecture. The approach taken depends on the source data store. DB2 is the most straightforward, since DB2 and Oracle are both relational databases. In addition to migrating the data, customers sometimes choose to perform data cleansing, field extensions, merge columns, or other data maintenance practices leveraging the automated tooling that synchronizes all data changes with changes to the application's data access code. Mainframe DB2 DB2 is a predominant relational database on IBM mainframes. When migrating to Oracle Database, the migration approach is highly automated, and resolves all discrepancies between the two RDBMS in terms of field formats as well as error codes returned to applications, so as to maintain application behavior unchanged, including stored procedures if any. IMS IMS/DB (also known as DL/1) is a popular hierarchical database for older applications. Creating appropriate relational data schema for this data requires an understanding of the application access patterns so as to optimize the schema for best performance based on the most frequent access paths. To minimize code impact, a translation layer can be used at run-time to support IMS DB style data access from the application, and map it to appropriate SQL calls. This allows the applications to interface with the segments, now translated as DB2 UDB or ORACLE tables, without impacting application code and maintenance. VSAM VSAM files are used for keyed-sequential data access, and can be readily migrated to ISAM files or to Oracle Database tables wherever transactional integrity is required (XA features). Some customers also choose to migrate VSAM files to Oracle Database to provide accessibility from other distributed applications, or to simplify the re-engineering required to extend certain data fields or merge multiple data sources. Meeting Performance and Other QoS Requirements The mainframe's performance, reliability, scalability, manageability, and other QoS attributes have earned it pre-eminence for business-critical applications. How well do re-hosting solutions measure up against these characteristics? Earlier solutions based on IBM CICS emulators derived from development tools often did not measure up to the demands of mainframe workloads since they were never intended for true production environment and have not been exposed to large-scale applications. As a result, they have only been used for re-hosting small systems under 300 MIPS and not requiring any clustering or distributed workload handling. Oracle Tuxedo was built to scale ground up, to support high performance telecommunications operations. It has the distinction of being the only non-mainframe TP solution recognized for its mainframe-like performance, reliability, and QoS characteristics. Most large enterprise customers requiring such capabilities in distributed systems have traditionally relied on Tuxedo. Consistently rated by IDC and Gartner as the market leader, and predominant in non-mainframe OLTP applications, it has also become the preferred COBOL/C application platform and transaction engine for re-hosted mainframe applications requiring high performance and/or mission-critical availability and reliability. Reasons for the broad recognition of Tuxedo as the only mainframe-class application platform and transaction engine for distributed systems are based on mainframe-class performance, scalability, reliability, availability, and other QoS attributes proven in multiple customer deployments. The following table highlights some of these capabilities:   Reliability Availability Guaranteed messaging and transactional integrity Hardened code from 25 years of use in the world's largest transaction applications Transaction integrity across systems and domains through a two phase commit (XA) for all resources such as databases, queues, and so on. Proven in mainframe-to-mainframe transactions and messaging No single point of failure, 99.999% uptime with N+1/N+2 clusters Application services upgradeable in operation Self-monitoring, automated fail-over, datadriven routing for super high availability Centralized monitoring and management with clustered domains; automated, lights-out operations     Workload Management   Performance and Scalability   Resource management and prioritization across Tuxedo services Dynamic load balancing across domains based on load conditions Data-driven routing enables horizontally distributed database grids and differentiated QoS End-to-end monitoring of Tuxedo system and application services enables SLA enforcement Virtualization support enables spawning of Tuxedo servers on demand Parallel processing to maximize resource utilization with low latency code paths that provide sub-second response at any load Horizontal and vertical scaling of system resources yields linear performance increases Request multiplexing (synchronous and asynchronous) maximizes CPU utilization Proven in credit card authorizations at over 13.5K tps, and in telco billing at over 56K tps. Middleware of choice in HP, Fujitsu, Sun, IBM, and NEC TPC-C benchmarks    
Read more
  • 0
  • 0
  • 3006

article-image-user-access-control-drupal-6
Packt
23 Oct 2009
16 min read
Save for later

User Access Control in Drupal 6

Packt
23 Oct 2009
16 min read
Before we continue, it is worth pointing out that at the moment of adding the basic functionality you are more than likely using the administrative user (user number 1) for all the site's development needs. That is absolutely fine, but once the major changes to the site are completed, you should begin using a normal administrative user that has only the permissions required to complete your day-to-day tasks. The next section will highlight the general philosophy behind user access, which should make the reason for this clear. Planning an Access Policy When you think about how your site should work, focus in on what will be required of yourself, other community members, or even anonymous users. For instance: Will there be a team of moderators working to ensure that the content of the site conforms to the dictates of good taste and avoids material that is tantamount to hate speech, and so on? Will there be subject experts who are allowed to create and maintain their own content? How much will anonymous visitors be allowed to become involved, or will they be forced to merely window shop without being able to contribute? Some of you might feel that the site should grow organically with the community, and so you want to be extremely flexible in your approach. However, you can take it as given that Drupal's access policies are already flexible, given how easy it is to reconfigure, so it is good practice to start out with a sensible set of access rules, even if they are going to change over time. If you need to make modifications later, so be it, but at least there will be a coherent set of rules from the start. The first and foremost rule of security that can be applied directly to our situation is Grant a user permissions sufficient for completing the intended task, and no more! Our entire approach is going to be governed by this rule. With a bit of thought you should be able to see why this is so important. The last thing anyone wants is for an anonymous user to be able to modify the personal blog of a respected industry expert. This means that each type of user should have carefully controlled permissions that effectively block their ability to act outside the scope of their remit. One upshot of this is that it is better to create a larger number of specific roles, rather than create a generic role or two, and allow everyone to use those catch-all permissions. A role constitutes a number of permissions that define what actions any members of that role can and can't perform. We will explore roles in detail in the next section! Drupal gives us fine-grained control over what users can accomplish, and you should make good use of this facility. It may help to think of your access control using the following figure (this does not necessarily represent the actual roles on your site—it's just an example): The shaded region represents the total number of permissions available for the site. Contained within this set are the various roles that exist either by default, like the Anonymous users role, or those you create in order to cater for the different types of users the site will require—in this case, the Blog Writer users and Forum Moderator users roles. From the previous diagram you can see that the Anonymous users role has the smallest set of permissions because they have the smallest area of the total diagram. This set of permissions is totally encapsulated by the Forum Moderator users and Blog Writer users—meaning that forum moderators and blog writers can do everything an anonymous user does, and a whole lot more. Remember, it is not compulsory that forum moderators encapsulate all the permissions of the anonymous users. You can assign any permissions to any role—it's just that in this context it makes sense that a forum moderator should be able to do everything an anonymous user can and more. Of course, the blog writers have a slightly different remit. While they share some privileges in common with the forum administrators, they also have a few of their own. Your permissions as the primary or administrative user encompass the entire set, because there should be nothing that you cannot control. It is up to you to decide which roles are best for the site, but before attempting this it is important to ask: What are roles and how are they used in the first place? To answer this question, let's take a look at the practical side of things in more detail. Roles It may seem a bit odd that we are not beginning a practical look at access control with a discussion on users. After all, it is all about what users can and cannot do! The problem with immediately talking about users is that the focus of a single user is too narrow, and we can learn far more about controlling access by taking a more broad view using roles. Once we have learned everything there is to know about roles, actually working with users becomes a trivial matter. As mentioned, a user role in Drupal defines a set of rules that must be obeyed by all the users in that role. It may be helpful to think of a role as a character in a play. In a play, an actor must always be true to their character (in the same way a user must be faithful to their role in Drupal)—in other words, there is a defined way to behave and the character never deviates (no matter which actor portrays the character). Creating a role in Drupal is very easy. Click the User management link under Administer and select the Roles tab to bring up the following: As you can see, we have two roles already defined by default—the anonymous user and the authenticated user. It is not possible to change these, and so the Operations column is permanently set to locked. To begin with, the anonymous user (this is any user who is browsing the site without logging in) has very few permissions set, and you would more than likely want to keep it this way, despite the fact it is possible to give them any and all permissions. Similarly, the authenticated user, by default, has only a few more permissions than the anonymous user, and it is also sensible to keep these to a minimum. We will see in a little while how to go about deciding who should have which permissions. In order to add a new role, type in a name for the role and click Add role, and you're done. But what name do you want to add? That's the key question! If you are unsure about what name to use, then it is most likely you haven't defined the purpose of the role properly. To see how this is done, let's assume we require a forum moderator who will be a normal user in every way, except for the ability to work directly on the forums (to take some of the burden of responsibility off the administrator's hands) to create new topics, and to edit the content if necessary. To get the ball rolling, type in forum moderator and click Add role—actually, you might even want to be more specific and use something like conservation forum moderator if there will be teams of forum moderators—you get the general idea. Now the roles page should display the new role with the option to edit it, shown in the Operations column. Click edit role in order to change the name of the role or delete it completely. Alternatively, click edit permissions to deal with the permissions for this specific role (we discuss permissions in a moment so let's leave this for now). Our work is just beginning, because now we need to grant or deny the various permissions that the forum moderator role will need in order to successfully fulfill its purpose. New roles are not given any permission at all to begin with—this makes sense, because the last thing we want is to create a role only to find that it has the same permissions as the administrative user. Chances are you will need to add several roles depending on the needs of the site, so add at least a blogger user that can edit their own blog—we will need a few different types to play with later on. Let's move on and take a look at how to flesh out this new role by setting permissions. Permissions In order to work with permissions, click the Permissions link under User management and you should be presented with a screen much like the following (notice the new forum moderator role on the right-hand side of the page): As you can see, this page lists all of the available permissions down the left-hand column and allows you to enable or disable that permission by checking or un-checking boxes in the relevant column. It is easy enough to see that one traverses the list, selecting those permissions required for each role. What is not so easy is actually determining what should and shouldn't be enabled in the first place. Notice too that the permissions given in the list on the left-hand side pertain to specific modules. This means that if we change the site's setup by adding or removing modules, then we will also have to change the permissions on this page. Most times a module is added, you will need to ensure that the permissions are set as required for that module, because by default no permissions are granted. What else can we learn from the permissions page shown in the previous screenshot? Well, what does each permission precisely mean? There are quite a few verbs that allow for completely different actions. The following lists the more common, generic ones, although you might find one or two others crop up every now and then to cater for a specific module: administer: gives the user the ability to affect the function of a module. For example, granting administer rights to the locale module means that the user can add or remove languages, manage strings, and even export .po files. This permission should only ever be given to trusted users, and never to anonymous users. access: gives the user the ability to make use of a module without being able to affect it in any way. For example, granting access rights to the comment module allows a user to view comments without being able to delete, edit, or reply to them. create: gives the user the ability to create content of some sort. For example, granting rights to create stories allows users to do so, but does not also give them the ability to edit those stories. edit any/own: gives the user the ability to work with either anyone's content or specifically the content they have created—depending on whether edit any or edit own is selected. For example, granting edit own rights to the blog module means that the user can modify their own blogs at will. delete any/own: applies to content related modules such as Node and empowers users to remove either anyone's content or confine them to removing only content posted by themselves. For example, setting delete own blog entry allows users to take back any blog postings they may regret having published. There are also other module-specific permissions available, and it is recommended that you play around and understand any new permission(s) you set. Previously, assigning the edit own permission automatically provided the delete own permission. For added security, delete own permissions for individual core content types have been removed from all roles and should be assigned separately. How do we go about setting up the required permissions for the forum moderator user? If we look down the list of permissions shown on the Permission page, we see the following forum-related options (at the moment, the forum moderator permissions are those in the outermost column): Enabling these three options, and then testing out what new powers are made available, should quickly demonstrate that this is not quite what we want. If you are wondering how to actually test this out, you need to create a new user and then assign them to the forum moderator role. The following section on Users explains how to create new users and administer them properly. Jump ahead quickly and check that out so that you have a new user to work with if you are unsure how it is done. The following point might make your life a bit easier: Use two browsers to test out your site. The demo site's development machine has IE and Firefox. Keep one browser for the administrator and the other for anonymous or other users in order to test out changes. This will save you from having to log in and log out whenever testing new permissions. When testing out the new permissions one way or another, you will find that the forum moderator can access and work with all of the forums—assuming you have created any. However, notice that there are node module permissions available, which is quite interesting because most content in Drupal is actually a node. How will this affect the forum moderator? Disable the forum module permissions for the forum moderator user and then enable all the node options for the authenticated user before saving and logging out. Log back in as the forum administrator and it will be clear that despite having revoked the forum based options for this user, it is possible to post to or edit anything in the forum quite easily by selecting the Create content link in the main menu. Is this what you expected? It should be precisely what you expect because the forum moderator is an authenticated user, so they have acquired the permissions that came from the authenticated user. In addition, the forum posts are all nodes, and any authenticated user can add and edit nodes, so even though the forum moderator is not explicitly allowed to work with forums, through generic node permissions we get the same result: Defined roles are given the authenticated user permissions. Actually, the result is not entirely the same because the forum moderator can now also configure all the different types of content on the site, as well as edit any type of content including other people's blogs. This is most certainly undesirable, so log back in as the primary user and remove the node permissions (except the first one) from the authenticated user role. With that done, you can now spend some time building a fairly powerful and comprehensive role-based access control plan. As an addendum, you might find that despite having a goodly amount of control over who does what, there are some things that are not easily done without help from elsewhere. Users A single user account can be given as many or as few permissions as you like via the use of roles. Drupal users are not really anything unless they already have a role that defines the manner in which they can operate within the Drupal framework. Hence, we discussed roles first. Users can be created in two ways. The most common way is by registering on the site—if you haven't already, go ahead and register a new user on your site by clicking the Create new account link on the homepage just to test things out. Remember to supply a valid email address otherwise you won't be able to sign in properly. This will create an authenticated user, with any and all permissions that have been assigned to the authenticated user role. The second way is to use the administrative user to create a new user. In order to do so, log on as the administrative user and click on Users in User management under Administer. Select the Add user tab and follow the instructions on that page. For example, I created a new forum moderator user by ensuring that the relevant role was checked: You will need to supply Drupal with usernames, email addresses, and passwords. Once there are a couple of users to play around with, it's time to begin working with them. Administering Users The site's administrator is given complete access to the other users' account information. By clicking on the edit link shown to the right of each user account (under the Operations column heading) in the Users page under User management, it is possible to make any changes you require to a given user. Before we do though, it's worth noting that the administration page itself is fairly powerful in terms of being able to administer individual users or groups of users with relative ease: The upper box, Show only users where, allows you to specify several filter conditions to cut down the result set and make it more manageable. This will become more and more important as the site accumulates more and more users. Once the various filter options have been implemented, the Update options allow you to apply whatever changes are needed to the list of users selected (by checking the relevant checkbox next to their name). Having both broad, sweeping powers as well as fine-grained control over users is one of the most valuable facilities provided by Drupal, and you will no doubt become very familiar with this page in due course. Click on the edit link next to the forum moderator user and take a look at the Roles section. Notice that it is now possible to stipulate which roles this user belongs to. At present there are only two new roles to be assigned (yours might vary depending on which roles have been created on your setup): Whenever a user is added to another role, they obtain the combined permissions of these roles. With this in mind, you should go about delegating roles in the following fashion: Define the most basic user of the site by setting the anonymous user permissions. Set permissions for a basic authenticated user (i.e. any Tom, Dick or Harry that registers on your site). Create special roles by only adding the specific additional permissions that are required by that role, and no more. Don't re-assign permissions that the authenticated user already has. Create new users by combining whatever roles are required for their duties or needs.
Read more
  • 0
  • 0
  • 3412
Modal Close icon
Modal Close icon